سؤال

هل هناك أي ممارسة جيدة تتعلق بمعالجة أخطاء Dynamic_cast (باستثناء عدم استخدامها عندما لا تضطر إلى ذلك)؟أنا أتساءل كيف يجب أن أتعامل مع NULL و bad_cast الذي يمكن أن يرميه.هل يجب أن أتحقق من كليهما؟وإذا اكتشفت Bad_cast أو اكتشفت NULL، فربما لا أستطيع التعافي على أي حال...في الوقت الحالي، أستخدم التأكيد للتحقق مما إذا كانdynamic_cast يُرجع قيمة غير فارغة.هل تقبل هذا الحل عند مراجعة الكود؟

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

المحلول

وإذا كان dynamic_cast <م> يجب النجاح، سيكون من ممارسة جيدة لاستخدام boost::polymorphic_downcast بدلا من ذلك، والذي يذهب قليلا شيئا من هذا القبيل:

assert(dynamic_cast<T*>(o) == static_cast<T*>(o));
return static_cast<T*>(o);

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

إذا كنت تشك في المدلى بها <م> قد فشل وكنت ترغب في الكشف عن ذلك، استخدم dynamic_cast ويلقي إلى نوع مرجع. هذا وسوف يلقي رمي bad_cast في حالة الخطأ، وسوف إنزال البرنامج. (وهذا أمر جيد إذا، كما تقول، انك لن يسترد أي حال)

T& t = dynamic_cast<T&>(o);
t.func(); //< Use t here, no extra check required

استخدم dynamic_cast إلى نوع المؤشر إلا إذا كان مؤشر-0 معنى في هذا السياق. قد ترغب في استخدامها في if مثل هذا:

if (T* t = dynamic_cast<T*>(o)) {
    t->func(); //< Use t here, it is valid
}
// consider having an else-clause

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

لإجابة على سؤالك مباشرة: كنت تفضل أحد البديلين الأولى لقد قدمت إلى وجود assert صريح في التعليمات البرمجية:)

نصائح أخرى

ويتم طرح bad_cast فقط عندما صب المراجع

dynamic_cast< Derived & >(baseclass)
وعاد

وNULL عندما صب المؤشرات

dynamic_cast< Derived * >(&baseclass)

وحتى لا يكون هناك ابدا اي حاجة للتحقق على حد سواء.

وتأكيد يمكن أن يكون مقبولا، ولكن ذلك يعتمد إلى حد كبير على السياق، ثم مرة أخرى، وهذا صحيح الى حد كبير كل ASSERT ...

نعم و لا.

boost::polymorphic_downcast<> هو بالتأكيد خيار جيد للتعامل مع أخطاء dynamic_cast<> خلال مرحلة التصحيح.ومع ذلك فمن الجدير أن نذكر ذلك polymorphic_downcast<> يجب أن تستخدم فقط عندما من الممكن التنبؤ بالنوع متعدد الأشكال الذي تم تمريره في وقت الترجمة, ، وإلا فإن dynamic_cast<> ينبغي أن تستخدم بدلا منه.

لكن تسلسل:

if (T1* t1 = dynamic_cast<T1*>(o)) 
{ }
if (T2* t2 = dynamic_cast<T2*>(o)) 
{ }
if (T3* t3 = dynamic_cast<T3*>(o)) 
{ }

يدل على تصميم سيء للغاية يجب تسويته تعدد الأشكال و وظائف افتراضية.

وهذا يعتمد ...؛ -)

إذا كنت أتوقع dynamic_cast حقا أن تعطيني شيئا صالحة للاستعمال، على سبيل المثال إذا كنت وليس لأحد غيرهم إضافة نوع متعدد الأشكال إلى وعاء يحتوي على مؤشرات إلى فئة أساسية، ثم أود أن أذهب مع المدلى بها إشارة والسماح للقتل std::bad_cast طلبي - لن تكون هناك أشياء أخرى كثيرة يجب القيام به، حقا

ولكن، إذا أنا الاستعلام عن نوع متعدد الأشكال عن بعض القدرة على كشفها بواسطة واجهة أنه لا يتعين بالضرورة أن تنفذ، ثم كنت اذهب مع المدلى بها المؤشر ومن ثم فإن NULL لا يكون خطأ ( ما لم يكن، بالطبع، لم أتوقع القدرة على حقا يكون هناك - ولكن بعد ذلك كنت قد ذهبت ليلقي الإشارة في المقام الأول ...)

وكنت أتفق مع 'ذلك يعتمد "الجواب، وأيضا إضافة" تدهور رشيقة ": لمجرد ان يلقي يفشل في مكان ليس سبب كاف للسماح للتطبيق تفشل (ويفقد المستخدم له / لها العمل، الخ .). أنصح مزيج من يؤكد والبرمجة الدفاعية:

ptr = dynamic_cast<MyClass>(obj);
ASSERT(ptr);
if(ptr)
{
   // do stuff
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top