سؤال

هذا السؤال لديه بالفعل إجابة هنا:

لدي فئة أ:

class A
{
    public:
        virtual double getValue() = 0;
}

والفئة ب:

class B : public A
{
    public:
        virtual double getValue() { return 0.0; }
}

وبعد ذلك في main() أفعل:

A * var;
var = new B[100];
std::cout << var[0].getValue(); //This works fine
std::cout << var[1].getValue(); //This, or any other index besides 0, causes the program to quit

إذا قمت بدلاً من ذلك بما يلي:

B * var;
var = new B[100];
std::cout << var[0].getValue(); //This works fine
std::cout << var[1].getValue(); //Everything else works fine too

كل شيء يتم تجميعه بشكل جيد، ولكن يبدو كما لو كان هناك خطأ ما في تعدد الأشكال الخاص بي؟أنا في حيرة.

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

المحلول

لا يمكنك التعامل مع المصفوفات بشكل متعدد الأشكال، لذلك new B[100] يخلق مجموعة من B كائنات وترجع مؤشرًا إلى المصفوفة - أو ما يعادل العنصر الأول في المصفوفة - وبينما يكون من الصحيح تعيين هذا المؤشر إلى مؤشر لفئة أساسية، فإنه غير صالح للتعامل مع هذا كمؤشر في مصفوفة من A أشياء.

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

نصائح أخرى

ليست هناك مشكلة في تعدد الأشكال ولكن في الطريقة التي تتعامل بها مع الذاكرة.سيتقدمك عامل التشغيل [] عبر المصفوفة بحجم البايتات (A) في الحالة الأولى وحجم البايتات (B) في الحالة الثانية.نظرًا لأن الكائنات من النوع B، فإن A* لا يشير إلى الموقع الصحيح في الذاكرة.

هنا طريقة أخرى للنظر إلى الأمر

char * var;
var = (char*) new B[100];
std::cout << ((A*)var[0]).getValue(); //This works fine
std::cout << ((A*)var[1]).getValue(); //This will fail
std::cout << ((A*)var[sizeof(B)]).getValue(); // should work

لم تقم بتخصيص الكائنات في المصفوفة:

for (int i=0;i<100;i++)
  var[i] = new B;

(على الرغم من أنني قد أخلط بين C++ و C#)

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