سؤال

أحتاج إلى تحويل نوع غير متكامل يحتوي على عنوان لنوع المؤشر الفعلي. يمكنني استخدام REISTERPRET_CAST كما يلي:

MyClass *mc1 = reinterpret_cast<MyClass*>(the_integer);

ومع ذلك، فإن هذا لا يقوم بأي شيكات وقت التشغيل لمعرفة ما إذا كان العنوان المعلق في الواقع يحمل كائن myclass. أريد أن أعرف ما إذا كان هناك أي فائدة في التحويل لأول مرة إلى الفراغ * (باستخدام إعادة تتريت reinterpret_cast) ثم استخدام Dynamic_cast حول النتيجة. مثله:

void *p = reinterpret_cast<void*>(the_integer);
MyClass *mc1 = dynamic_cast<MyClass*>(p);
assert(mc1 != NULL);

هل هناك أي ميزة في استخدام الطريقة الثانية؟

هل كانت مفيدة؟

المحلول

اكتب التحقق من dynamic_cast يتم تنفيذ بطرق مختلفة من خلال تطبيقات C ++ المختلفة؛ إذا كنت تريد إجابة لتنفيذك المحدد، فيجب أن تذكر ما هو التطبيق الذي تستخدمه. الطريقة الوحيدة للإجابة على السؤال بشكل عام هي الإشارة إلى ISO Standard C ++.

من خلال قراءتي القياسية، اتصل dynamic_cast على مؤشر الفراغ غير قانوني:

dynamic_cast<T>(v)

"إذا كان T هو نوع مؤشر، يكون V RValue لمؤشر لإكمال نوع الفصل"

(من 5.2.7.2 من معيار ISO C ++). void ليس نوع فئة كاملة، وبالتالي فإن التعبير غير قانوني.

ومن المثير للاهتمام، النوع يجري يلقي ل يسمح ليكون مؤشر الفراغ، أي

void * foo = dynamic_cast<void *>(some_pointer);

في هذه الحالة، dynamic_cast ينجح دائما، والقيمة الناتجة هي مؤشر إلى الكائن المشتق لأشار إليه v.

نصائح أخرى

لا، ليس هناك ميزة محددة في القيام بذلك. اللحظة التي تستخدمها reinterpret_cast, ، انتهت الرهانات. الأمر متروك لك للتأكد من أن المصبوب صالح.

في الواقع لا ميزة جادة. إذا كان الفراغ * يشير إلى شيء ليس مؤشرا لكائن متعدد الألوان تديره إلى سلوك غير محدد (عادة انتهاك وصول) على الفور.

الطريقة الآمنة هي الاحتفاظ بسجل لجميع كائنات myclass مباشرة. من الأفضل الحفاظ على هذا السجل في std::set<void*>, ، مما يعني أنه يمكنك بسهولة إضافة وإزالة وعناصر الاختبار.

سبب تخزينها كما void*S هو أنك لا تخاطر بشدة مثل إنشاء غير إجمالي MyClass* مؤشرات من الأعداد الصحيحة الخاصة بك.

  • بادئ ذي بدء "إعادة تفسير" int ل void * هي فكرة سيئة. إذا sizeof(int) هو 4 و sizeof(void *) هو 8 (نظام 64X) هو سوء تشكيل.

  • وعلاوة على ذلك dynamic_cast صالحة فقط لحالة الطبقات متعددة الجنسيات.

الخيار 1 هو خيارك الوحيد (شبه) الخاص بك.

الخيار 2: غير صالح C ++ كما Dynamic_Cast (مع عدم السماح باطل).

عند مستوى التنفيذ، يتطلب نوع المعلومات من نوع المصدر للوصول إلى نوع الوجهة. لا توجد طريقة (أو قد تكون هناك طريقة) للحصول على معلومات نوع مصدر وقت التشغيل من الفراغ * لذلك هذا غير صالح أيضا.

يستخدم Dynamic_Cast ل CAS UP UPD التسلسل الهرمي للنوع وليس من أنواع غير معروفة.

كملاحظة جانبية، ربما يجب أن تستخدم الفراغ * بدلا من عدد صحيح لتخزين مؤشر غير مصقول. هناك احتمال لعدم أن تكون كثيرة بما يكفي لتخزين مؤشر.

الطريقة الأكثر أمانا للتعامل مع المؤشرات في C ++ هي التعامل معها. هذا يعنى:

  • لا تخزن أبدا مؤشرات في أي شيء آخر غير مؤشر
  • تجنب مؤشرات الفراغ
  • أبدا تمرير المؤشرات إلى العمليات الأخرى
  • النظر في ضعيف_PTR إذا كنت تخطط لاستخدام مؤشرات على المواضيع

السبب في ذلك هو: ما تخطط للقيام به هو غير آمن ويمكن تجنبه إلا إذا كنت تتوافق مع رمز غير آمن (LEGACY؟). في هذه الحالة، فكر في إجابة MSALTERS، ولكن كن على علم بأنه لا يزال متاعب.

إذا كنت تعرف بالتأكيد ذلك the_integer يشير إلى فئة قاعدة معروفة (تحتوي على عضو افتراضي واحد على الأقل)، قد تكون هناك ميزة في الواقع: معرفة أن الكائن من فئة مشتقة محددة. ولكن عليك أن reinterpret_cast إلى الطبقة الأساسية أولا ثم القيام dynamic_cast:

BaseClass* obj = reinterpret_cast<BaseClass*>(the_integer);
MyClass* myObj = dynamic_cast<BaseClass*>(obj);

باستخدام أ void* في dynamic_cast لا طائل منه وعناية ببساطة. لا يمكنك استخدام dynamic_cast للتحقق مما إذا كان هناك كائن صالح في موقع تعسفي في الذاكرة.

يجب عليك أيضا الانتباه عند تخزين العناوين في متغيرات نوع غير مؤشر. هناك بنية حيث المقاومة (باطلة *)! = Sizeof (int)، مثل LP64.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top