Подробности реализации виртуальной диспетчеризации

Прежде всего, Я хочу прояснить, что я понимаю, что в стандарте C ++ нет понятия vtables и vptrs . Однако я думаю, что практически все реализации реализуют виртуальный механизм диспетчеризации примерно одинаково (поправьте меня, если я ошибаюсь, но это не главный вопрос). Кроме того, я считаю , что я знаю, как работают виртуальные функции , то есть я всегда могу сказать, какая функция будет вызвана, мне просто нужны детали реализации.

Предположим, кто-то спросил меня следующее:
«У вас есть базовый класс B с виртуальными функциями v1, v2, v3 и производный класс D: B, который переопределяет функции v1 и v3 и добавляет виртуальную функцию v4. Объясните, как работает виртуальная диспетчеризация».

Я бы ответил так:
Для каждого класса с виртуальными функциями (в данном случае B и D) у нас есть отдельный массив указателей на функции, называемый vtable.
Vtable для B будет содержать

&B::v1
&B::v2
&B::v3

vtable для D будет содержать

&D::v1
&B::v2
&D::v3
&D::v4 

Теперь класс B содержит указатель на член vptr. D естественно наследует его и, следовательно, тоже содержит. В конструкторе и деструкторе BB устанавливает vptr так, чтобы указывать на vtable B. В конструкторе и деструкторе DD устанавливает его так, чтобы он указывал на vtable D.
Любой вызов виртуальной функции f на объекте x полиморфного класса X интерпретируется как вызов x.vptr [позиция f в vtables]

Вопросы:
1. Есть ли у меня ошибки в приведенном выше описании?
2. Как компилятор узнает позицию f в vtable (подробно, пожалуйста)
3. Означает ли это, что если у класса две базы, то у него есть два vptr? Что в этом случае происходит? (постарайтесь описать так же, как я, как можно подробнее)
4. Что происходит в алмазной иерархии с A наверху, B, C в середине и D внизу? (A - виртуальный базовый класс для B и C)

Заранее спасибо.

31
задан user3286661 12 June 2018 в 11:49
поделиться