TL;DR
Решил изучить устройство таблиц виртуальных функций, т.к. слышал что об этом могут спрашивать на собеседовании.
Естественно начал экспериментировать с размером класса для интереса. Сам собой, нашелся хитроватый примерчик, который и дал начало моему вопросу.
Сразу отмечу, что компилирую только с помощью GCC и стараюсь придерживаться стандарта. Я в целом понимаю, как происходит управление памятью при создании/удалении объектов класса. Но вот не нашел в стандарте ни слова о том как создается таблица виртуальных функций в таком случае.
Описание задачи
У нас есть пустой класс. По стандарту c++, размер его объектов будет равен минимально адресуемой единице - 1 байту.
После добавления виртуальной функции размер объекта уже будет равен 4 байтам - размеру указателя на таблицу виртуальных функций.
Пример №1class A
{
//sizeof(BaseA) = 1 byte
}
class B
{
virtual void foo() {...}
//sizeof(B) = 4 byte
}
Теперь усложняем пример и добавим еще два класса, в каждом по виртуальной функции, а потом отнаследуемся от них пустым классом. Получим вот что:
Пример №2class BaseA
{
virtual void foo()
{
}
};
class BaseB
{
virtual void foo()
{
}
};
class Derived : BaseA, BaseB
{
};
Сколько будет занимать объект класса Derived? Пока очевидно, что это будет 4byte указатель на ТВФ класса BaseA + 4byte указатель на ТВФ BaseB, и того:
sizeof(Derived) = 8
Тут-то и начинается самое интересное, сколько памяти будет занимать объект класса Derived со своей собственной виртуальной функцией?
Пример №3#include <iostream>
using namespace std;
class BaseA
{
virtual void foo()
{
}
};
class BaseB
{
virtual void foo()
{
}
};
class DerivedWithVirtual : BaseA, BaseB
{
virtual void bar()
{
}
};
class DerivedWithoutVirtual : BaseA, BaseB
{
};
int main()
{
cout << "Size of Base class A: "
<< sizeof(BaseA) << endl;
cout << "Size of Base class B: "
<< sizeof(BaseB) << endl;
cout << "Size of derived class with virtual function: "
<< sizeof(DerivedWithVirtual) << endl;
cout << "Size of derived class without virtual function: "
<< sizeof(DerivedWithoutVirtual) << endl;
system("pause");
return 0;
}
Вот что он выведет:
Вывод примера №3Size of Base class A: 4
Size of Base class B: 4
Size of derived class with virtual function: 8
Size of derived class without virtual function: 8
Сам вопрос
Почему у объектов класса DerivedWithVirtual не появляется указателя на свою таблицу виртуальный функций и куда записывается указатель на функцию DerivedWithVirtual::bar?