في C ++ ، تحقق مما إذا كانت حالتان من الفئة الأساسية هما Infact من الفئة الفرعية نفسها

StackOverflow https://stackoverflow.com/questions/3863567

  •  27-09-2019
  •  | 
  •  

سؤال

يشرح الرمز أدناه المشكلة. املأ Same_Sub_Class لاكتشاف ما إذا كانت المؤشرتان إلى الفئة A الأساسية الافتراضية هي في الواقع نفس الفئة الخرسانية.

struct A {
    ...
}:

struct B : public A {
    ...
}:

struct C : public A {
    ...
}


bool same_sub_class(A * a1, A * a2){
    // Fill this in to return true if a1 and a2 are
    // of the same concrete class
}

تعديل:

عندما أنظر إلى طلبي ، أحتاج إلى شيء مختلف قليلاً عن ما سبق. أحتاج إلى أن أكون قادرًا على تجميع مثيلات من خلال type_id.

لعِلمِكَ. لديّ نظام ألغبرا رمزيًا صغيرًا حتى أقوم بالتلاعب ، من المهم معرفة نوع الفصل في بعض الأحيان للفرز وإعادة ترتيب التعبيرات.

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

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

المحلول

إذا كنت تستطيع استخدام RTTI ،

typeid(*a1) == typeid(*a2)

أعتقد أنك تحتاج أيضًا إلى

#include <typeinfo>

ويجب أن يكون لديك وظيفة افتراضية في فصولك بحيث يكون VTABLE موجودًا-يجب أن يكون المدمر جيدًا.

تحديث:

لست متأكدًا من أنني أفهم تمامًا ما هي متطلباتك للتجميع (هل تحتاج إلى نوع من الطلبات الحتمية؟ القيمة عاد من typeid مشغل إلى:

  • تجزئة السلسلة التي تم إرجاعها من typeid(*ptr).name()
  • يستخدم typeid(*a1).before(typeid(*a2)) كمعيار طلب. هذا لا يحتوي على أي حتمية بين الركض ، رغم ذلك.

بشكل عام عند التفكير في RTTI ، من الجيد معرفة ما إذا كان يمكن تحقيق أي من هذا بشكل أفضل باستخدام وظائف افتراضية جيدة التصميم (إرسال مزدوج, ، فمثلا). لا أستطيع حقًا أن أقول ما إذا كان هناك بديل جيد في قضيتك ، لأنني لا أفهم التفاصيل.

نصائح أخرى

typeid(*a1) == typeid(*a2)

لاحظ dereference ، من المهم.

يمكنك جعل معرف النوع الخاص بك:

struct A{
...
protected:
 enum TypeTag{B_TYPE, C_TYPE};
 TypeTag typeTag;
};

ثم في مُنشئو الفئات الفرعية:

B::B()
: typeTag(TypeTag::B_TYPE)
{
...
}

C::C()
: typeTag(TypeTag::C_TYPE)
{
...
}

هناك ميزة في C ++ تسمى RTTI (معلومات نوع وقت التشغيل) والتي تتيح لك القيام مثل هذه الأشياء.

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

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

(أ) إذا كنت أرغب في تخزين كائنات typeinfo في unordered_set ، فما الذي يجب أن أفعله؟

reportInfo دعم طريقة == وطريقة الاسم (). يمكن استخدام الاسم لإنشاء تجزئة و == للمساواة

(ب) إذا أردت تخزين كائنات typeinfo في order_set (std :: set) ، فما الذي يجب أن أفعله؟

TypeInfo يدعم == وطريقة قبل (). مع القليل من تغليف هاتين الطريقتين ، يمكنني تنفيذ واجهة لوظيفة مقارنة تعطيني ترتيبًا ضعيفًا.

خدعة واحدة قد تعمل أو لا تعمل مع RTTI ، اعتمادًا على المترجم الخاص بك ، هي ما يلي

const type_info &a1_type_info= typeid(*a1);
const type_info &a2_type_info= typeid(*a2);

return &a1_type_info==&a2_type_info || a1_type_info==a2_type_info;

إذا كان المترجم الخاص بك يخلق type_info مثيلات حسب القيمة ، سيفشل هذا الاختبار الأول ولكنه ينجح في الاختبار الثاني. إذا قام المترجم الخاص بك بتخزين الحالات ، فسوف ينجح الاختبار الأول (إذا كان نفس النوع) ويكون أسرع بكثير لأنه مجرد مؤشر مقارنة. إذا كان المترجم الخاص بك يعيد مثيلات مختلفة بسبب a1 و a2 جاء من مكتبات مشتركة مختلفة ، يجب أن لا يزال يعمل.

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