Dynamic_cast من "void *"
-
29-09-2019 - |
سؤال
وفق هذه, void*
ليس لديه معلومات RTTI ، وبالتالي يلقي من void*
ليس قانونيا وهذا منطقي.
إذا كنت أتذكر بشكل صحيح، dynamic_cast
من void*
كان يعمل على مجلس التعاون الخليجي.
هل يمكنك توضيح المشكلة من فضلك.
المحلول
dynamic_cast
يعمل فقط على أنواع الأشكال ، أي فئات تحتوي على وظائف افتراضية.
في مجلس التعاون الخليجي يمكنك dynamic_cast
إلى void*
لكن لا من:
struct S
{
virtual ~S() {}
};
int main()
{
S* p = new S();
void* v = dynamic_cast<void*>(p);
S* p1 = dynamic_cast<S*>(v); // gives an error
}
نصائح أخرى
في 5.2.7 - Dynamic cast [expr.dynamic.cast]
تقول ذلك ل dynamic_cast<T>(v)
:
- إذا
T
هو نوع المؤشر ،v
يجب أن يكون rvalue من المؤشر لإكمال نوع الفصل - إذا
T
هو نوع مرجعي ،v
يجب أن يكون lvalue لنوع الفصل الكامل (شكرًا usta للتعليق على هذا المفقود)
...
- خلاف ذلك،
v
يجب أن يكون مؤشرًا أو lvalue من نوع متعدد الأشكال
لذلك ، لا ، أ (void*)
القيمة غير مسموح.
دعونا نفكر في ما قد يعنيه طلبك: قل أنك حصلت على مؤشر حقًا Derived1*
, ، لكن الرمز dynamic_cast
-نغ فقط يعلم أنه ملف void*
. دعنا نقول أنك تحاول إلقاءها على Derived2*
, ، حيث كل من الفئتين المشتقة لها قاعدة مشتركة. بشكل سطحي ، قد تعتقد أن جميع المؤشرات ستشير إلى نفس الشيء Base
الكائن ، الذي سيحتوي على مؤشر لجدول الإرسال الظاهري ذي الصلة و RTTI ، لذلك يمكن أن يتم تعليق كل شيء معًا. ولكن ، ضع في اعتبارك أن الفئات المشتقة قد تحتوي على فئات أساسية متعددة ، وبالتالي المطلوبة Base
قد لا يكون الكائن الفرعي للفئة هو الذي Derived*
- متاح فقط كملف void*
- يشير. لن ينجح. الخلاصة: يحتاج المترجم إلى معرفة هذه الأنواع حتى يتمكن من إجراء بعض التعديل على المؤشرات بناءً على الأنواع المعنية.
Derived1* -----> [AnotherBase] [[VDT]Base] <-- but, need a pointer to start of [extra members] this sub-object for dynamic_cast
(تتحدث بعض الإجابات عن الحاجة إلى المؤشر الذي يلقي من نوعه من النوع متعدد الأشكال ، ولديه وظائف افتراضية. هذا كل شيء صالح ، ولكن مضللة بعض الشيء. كما ترون أعلاه ، حتى لو كان void*
هو بالنسبة لمثل هذا النوع ، فإنه لا يزال يعمل بشكل موثوق بدون معلومات النوع الكامل ، لأن المشكلة الحقيقية هي ذلك void*
يُفترض أنه يشير إلى بداية الكائن المشتق ، في حين أنك تحتاج إلى مؤشر إلى كائن فرعي من الفئة الأساسية يستمد منه النوع إلى النوع.)
صحيح ان void*
لا يمكن أن يكون dynamically_cast
إد من.
ربما تكون سوءًا. مع G ++ 4.5 والرمز التالي
struct A {
virtual ~A();
};
int main() {
A a;
void *p = &a;
A* pa = dynamic_cast<A*>(p);
}
أحصل على الخطأ التالية:
لا يمكن dynamic_cast 'p' (من النوع "void*') لكتابة" الهيكل A*"(المصدر ليس مؤشرًا للفصل)
أعتقد أنك تخلط بين dynamic_cast
إلى void*
. هذا قانوني ويحصل على المؤشر إلى كائن الطبقة الأكثر اشتقاقًا.
dynamic_cast
من void*
غير قانوني - النوع الذي تم إلقاؤه من تعدد الأشكال - يحتوي على وظيفة افتراضية واحدة على الأقل (تعداد المدمر الافتراضي أيضًا).
يمكنك إلقاء مؤشر إلى النوع متعدد الأشكال إلى void *
, ، ولكن ليس العكس.