Ответ
vtable создается, когда объявление класса содержит виртуальную функцию. Vtable вводится, когда родитель - где-нибудь в иерархии - имеет виртуальную функцию, давайте вызовем этого родителя Y. У любого родителя Y не будет vtable (если у них нет virtual
для какой-то другой функции в их иерархии ).
Читайте дальше для обсуждения и тестирования
- объяснение -
Когда вы указываете функцию-член как виртуальную, есть вероятность, что вы можете попытаться использовать подклассы через базовый класс полиморфно во время выполнения. Чтобы сохранить гарантию производительности C ++ по сравнению с языковым дизайном, они предложили максимально легкую стратегию реализации - то есть один уровень косвенности, и только тогда, когда класс может использоваться полиморфно во время выполнения, и программист определяет это, устанавливая по крайней мере одну функцию как виртуальная.
Вы не несете стоимость виртуальной таблицы, если избегаете виртуального ключевого слова.
- редактировать: отразить ваши изменения -
Только когда базовый класс содержит виртуальную функцию, любые другие подклассы содержат vtable. Родители указанного базового класса не имеют vtable.
В вашем примере все три класса будут иметь vtable, потому что вы можете попробовать использовать все три класса через A*.
- тест - GCC 4+ -
#include <iostream>
class test_base
{
public:
void x(){std::cout << "test_base" << "\n"; };
};
class test_sub : public test_base
{
public:
virtual void x(){std::cout << "test_sub" << "\n"; } ;
};
class test_subby : public test_sub
{
public:
void x() { std::cout << "test_subby" << "\n"; }
};
int main()
{
test_sub sub;
test_base base;
test_subby subby;
test_sub * psub;
test_base *pbase;
test_subby * psubby;
pbase = ⊂
pbase->x();
psub = &subby;
psub->x();
return 0;
}
выход
test_base
test_subby
test_base
не имеет виртуальной таблицы, поэтому все, что будет к ней применено, будет использовать x()
из test_base
. test_sub
, с другой стороны, меняет природу x()
, и его указатель будет косвенным через vtable, и это показывает, что test_subby
x()
выполняется.
Итак, vtable вводится в иерархию только при использовании ключевого слова virtual. У более старых предков нет vtable, и если произойдет уныние, он будет привязан к функциям предков.