Таблица виртуальных функций множественного наследования
Пример кода следующий:
class A
{
public:
int k;
virtual int f();
};
class B:public virtual A
{
public:
virtual int a();
};
int main()
{
cout<<sizeof(A)<<sizeof(B);
}
Это печатает
8 12
Похоже на то class B
имеет собственную новую таблицу виртуальных функций.
Если class A
изменения в:
class A
{
public:
virtual int f();
};
Это печатает
4 4
Кто-нибудь может объяснить причину?
2 ответа
В вашем подклассе B B является виртуальным подклассом A. Таким образом, B имеет отдельный указатель vtbl (4 байта) поверх того, что есть у подобъекта A. Таким образом,
sizeof(B object)
= sizeof(A object) + sizeof (vtbl pointer of B)
= sizeof(int) + sizeof (vtbl pointer of A) + sizeof (vtbl pointer of B)
= 4 + 4 + 4
= 12
А также,
sizeof(A object)
= sizeof(int) + sizeof (vtbl pointer of A)
= 4 + 4
= 8
Если B нормальный подкласс A,
sizeof(B object)
= sizeof(A object)
= sizeof(int) + sizeof (vtbl pointer of A)
= 4 + 4
= 12
Для пустого класса A минимальный размер, выделенный для sizeof A, равен sizeof указателя vtbl = 4. А поскольку A пуст с точки зрения данных экземпляра, виртуальное наследование для пустого класса не увеличивает размер объекта.
В контексте наследования классов "виртуальный" означает "определенный во время выполнения". Есть две отдельные вещи, которые могут быть виртуальными, и что реализация должна как-то реализовываться:
виртуальные функции, для которых фактическая функция, которая должна быть вызвана, должна быть определена во время выполнения:
x.f()
- ктоf
? Обычные реализации включают таблицы указателей функций.виртуальное наследование, при котором подобъект виртуальной базы неизвестен до времени выполнения. Реализация должна предоставить механизм для определения местоположения фактического базового объекта:
x.a = 10
- гдеa
? Обычные реализации для этого включают вычисления смещения указателя.
Если виртуальный базовый класс не имеет состояния (это похоже, но не эквивалентно "пусто"), то второй вариант использования становится пустым. Поскольку нет элементов данных, чье местоположение должно быть определено динамически, реализации не нужно генерировать какую-либо информацию для этого, а также объектам не нужно хранить соответствующие ссылки.
Один популярный C++ ABI, Itanium ABI, подробно описывает, как реализуется виртуальность. Есть также эта популярная статья, объясняющая эту реализацию.