Почему порядок наследования или сопоставление влияет на индекс vftable? (для VSC для C++)

Немного поигравшись с полиморфизмом, я попытался сделать что-то вроде следующего:

class a { virtual void method() { } };
class b { virtual void method() { } };
class c : public a, b {
    virtual void method() { }
    virtual void anotherMethod() { } // (1)
};
class d : public c, a, b // (2)
{ virtual void method() { } }; // C2369

Насколько мне известно, это должно работать без проблем. Но компилятор говорит: error C2369: 'const d::'vftable'{for 'a'}' : redefinition; different subscripts И я понятия не имею, почему это происходит. Есть три способа устранить эту ошибку: либо удалить метод (1), либо изменить порядок наследования (2). Изменить. Эту проблему также может решить применение виртуального наследования. Таким образом, кажется, что порядок наследования или сопоставление влияет на vftable. vftable — это массив для отображений виртуальных функций-членов, также известный как. динамическое связывание в C++.

Поэтому я также просмотрел документацию Microsoft по C2369. где они показывают это в качестве примера, как воспроизвести эту ошибку:

int a[10];
int a[20];   // C2369
int b[20];   // OK

Другими словами, изменение порядка наследования меняет индекс этой таблицы?! Любые идеи?


person Christoph Meißner    schedule 02.07.2012    source источник
comment
Возможно virtual наследование? en.wikipedia.org/wiki/Virtual_inheritance   -  person BoBTFish    schedule 02.07.2012
comment
Да, это также, кажется, решает эту проблему, я добавлю это к моему вопросу. Но я до сих пор не понимаю, почему это влияет на индекс vftable.   -  person Christoph Meißner    schedule 02.07.2012


Ответы (1)


Классы по умолчанию наследуются частным образом (в отличие от структур)! Следовательно, "c" публично наследуется только от "a"! Вам не хватает еще одного открытого ключевого слова:

class c : public a, public b

Другая проблема, с которой вы сталкиваетесь, заключается в том, что вы наследуете два класса, которые определяют одну и ту же функцию-член. a::method не соответствует тому же адресу, что и b::method! Ваша следующая проблема, вероятно, будет заключаться в том, что вызовы «метода» неоднозначны...

person MFH    schedule 02.07.2012
comment
Да, конечно, это тот случай, который я хотел проверить, играя. И да, вы правы, адрес a::method не соответствует b::method. Но разве компилятор не должен решить эту проблему? Кстати: добавление общедоступных модификаторов ничего не меняет, на мой взгляд. - person Christoph Meißner; 02.07.2012
comment
Вы получите только один void method() в d. См. stackoverflow.com/questions/5545897/ (хотя он цитирует старый стандарт). - person BoBTFish; 02.07.2012
comment
Он не может решить эту проблему, потому что эти две функции-члены не обязательно совпадают! Если бы компилятор сделал это, это нарушило бы идею множественного наследования на фундаментальном уровне... - person MFH; 02.07.2012
comment
Это то, что я ожидал, что этот пример должен сделать/показать. И именно в этом проблема, я думаю. vftable должен содержать этот единственный метод, потому что оба объявления переопределены/скрыты (?) в class d + дополнительный метод (2) class c. - person Christoph Meißner; 02.07.2012