2016-08-16 5 views
0

Я знаю, что компилятор дает ошибку для двусмысленности, если мы не упоминаем виртуальное ключевое слово при выводе дочернего класса в проблему с алмазом. Итак, как виртуальное ключевое слово устраняет эту двусмысленность?Как виртуальное ключевое слово разрешает двусмысленность в множественном наследовании?

+6

Видимый дубликат: [Как виртуальное наследование разрешает двусмысленность «бриллианта» (множественное наследование)?] (Http://stackoverflow.com/q/2659116/1149924) – kkm

ответ

0

От isocpp faq

class Base { 
public: 
    // ... 
protected: 
    int data_; 
}; 
class Der1 : public virtual Base { 
        ↑↑↑↑↑↑↑ // This is the key 
public: 
    // ... 
}; 
class Der2 : public virtual Base { 
        ↑↑↑↑↑↑↑ // This is the key 
public: 
    // ... 
}; 
class Join : public Der1, public Der2 { 
public: 
    void method() 
    { 
    data_ = 1; // Good: this is now unambiguous 
    } 
}; 
int main() 
{ 
    Join* j = new Join(); 
    Base* b = j; // Good: this is now unambiguous 
} 

, если вы не указали наследование как виртуальный, компилятор попытается добавить два Base классов в Derived объекта, и он не будет знать, какие data_ заполнить . У вас будет фактически два объекта, которые будут одинаковыми в вашем производном классе. Объявление наследования как virtual сообщает компилятору, что вы хотите получить только один экземпляр базового класса в производном классе.

+0

Спасибо dau_sama. В этом случае размер класса Join равен 12, которые включают в себя 2 виртуальных указателя Der1, Der2 и 4 байта данных (я думаю). Правильно ли это? Также какой путь используется компилятором для поддержки одиночной копии базового объекта? – DevMJ

+0

Я думаю, что это правильно в gcc/x86, но это реализация определена. Вероятно, на других архитектурах это может быть реализовано по-другому. В этом простом случае компилятор просто знает, что он должен только зарезервировать один экземпляр базового объекта в макете памяти. –

Смежные вопросы