سؤال

دعونا نقول لدي قاعدة الدرجة عدة المشتقة فصول.هل هناك أي طريقة أن يلقي كائن إلى واحدة من الفئات المشتقة من دون الحاجة إلى كتابة شيء مثل هذا :


string typename = typeid(*object).name();
if(typename == "Derived1") {
   Derived1 *d1 = static_cast< Derived1*>(object);
}
else if(typename == "Derived2") {
   Derived2 *d2 = static_cast < Derived2*>(object);
}
...
else {
  ...
}
هل كانت مفيدة؟

المحلول

لا.

تقرأ على تعدد الأشكال.تقريبا كل الديناميكية "الزهر" الوضع مثال تعدد الأشكال تكافح من أجل تنفيذها.

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

نسيت أهم جزء من المثال الخاص بك.مفيدة, متعددة الأشكال العمل.

string typename = typeid(*object).name();
if(typename == "Derived1") {
   Derived1 *d1 = static_cast< Derived1*>(object);
   d1->doSomethingUseful();
}
else if(typename == "Derived2") {
   Derived2 *d2 = static_cast < Derived2*>(object);
   d2->doSomethingUseful();
}
...
else {
  ...
}

إذا كل فئة فرعية تنفذ doSomethingUseful هذا هو أبسط من ذلك بكثير.ومتعددة الأشكال.

object->doSomethingUseful();

نصائح أخرى

يمكنك استخدام dynamic_cast و اختبار NULL, ولكن أود أن بقوة النظر في إعادة بيع ديون رمز بدلا من ذلك.

إذا كنت في حاجة فرعية محددة في التعامل ، طريقة القالب قد تكون مفيدة, ولكن من دون معرفة ما تحاول أن يحققوه ، إنها غامضة تخمين.

Derived1* d1 = dynamic_cast< Derived1* >(object);
if (d1 == NULL)
{
    Derived2* d2 = dynamic_cast< Derived2* >(object);
    //etc
}

لدي الطرق التالية على smartpointer نوع محاكاة C# 'هو' و 'ك':

template< class Y > bool is() const throw()
    {return !null() && dynamic_cast< Y* >(ptr) != NULL;}
template< class Y > Y* as() const throw()
    {return null() ? NULL : dynamic_cast< Y* >(ptr);}

يمكنك القيام بذلك باستخدام dynamic_cast, ه.g:

if ( Derived1* d1 = dynamic_cast<Derived1*>(object) ) {
    // object points to a Derived1
    d1->foo();
}
else if ( Derived2* d2 = dynamic_cast<Derived2*>(object) ) {
    // object points to a Derived2
    d2->bar();
}
else {
    // etc.
}

ولكن كما قال آخرون ، رمز مثل هذا يمكن أن تشير إلى سوء التصميم ، يجب أن تستخدم عموما وظائف افتراضية لتنفيذ متعددة الأشكال السلوك.

وعادة ما يكون هذا هو علامة سيئة التصميم.لماذا تريد أن تفعل هذا ؟ فإنه قد يكون من الممكن تصميم بحيث ليست هناك حاجة.

ما كنت تحاول إنجاز بالضبط ؟ في تجربتي, مثل هذه الامور هي علامة سيئة التصميم.إعادة تقييم الدرجة الهرمي ، لأن الهدف من وجوه المنحى والتصميم هو جعل مثل هذه الأشياء لا لزوم لها.

المثال الخاص بك لن الميناء ، لأن نفس شكل اسم() ليست محددة.قد تتمكن من محاولة خلافة dynamic_casts. Dynamic_cast بإرجاع مؤشر فارغة إذا كنت الزهر إلى نوع خاطئ.ومع ذلك ، إذا كنت تفعل typeswitch مثل هذا واحد, هناك شيء خاطئ مع التصميم الخاص بك.

أعتقد dynamic_cast هو الطريق للذهاب, ولكن أنا لا أعتقد أن هذا هو سوء تصميم جميع الظروف الممكنة لأنه كائن أن يكون مسبوك قد يكون شيئا التي تقدمها بعض طرف ثالث وحدة.دعونا نقول كائن تم إنشاؤه من قبل المكونات في أن مؤلف التطبيق لا يوجد لديه المعرفة.و خاصة في المكونات قد خلق Derived1 (يجري النسخة القديمة) نوع الكائن أو Derived2 (يجري النسخة الجديدة) نوع الكائن.ربما المكونات في واجهة ليست مصممة للقيام الإصدار أشياء محددة ، فإنه يخلق فقط الكائن وبالتالي فإن التطبيق يجب أن تفعل هذا النوع من التدقيق لضمان الصب/التنفيذ.بعد هذا يمكننا بأمان استدعاء كائن.doSomethingUsefulThatDoesNotExistinderived1();

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