Какая виртуальная таблица будет чистой расположенной виртуальной функцией? В базовом классе или производном классе?
Например, на что виртуальная таблица похожа в каждом классе?
class Base {
virtual void f() =0;
virtual void g();
}
class Derived: public Base{
virtual void f();
virtual void g();
}
g++ -fdump-class-hierarchy layout.cpp
выдает файл layout.cpp.class
. Содержимое layout.cpp.class
покажет следующее:
Vtable for Base Base::_ZTV4Base: 4u entries 0 (int (*)(...))0 8 (int (*)(...))(& _ZTI4Base) 16 __cxa_pure_virtual 24 Base::g Class Base size=8 align=8 base size=8 base align=8 Base (0x7ff893479af0) 0 nearly-empty vptr=((& Base::_ZTV4Base) + 16u) Vtable for Derived Derived::_ZTV7Derived: 4u entries 0 (int (*)(...))0 8 (int (*)(...))(& _ZTI7Derived) 16 Derived::f 24 Derived::g Class Derived size=8 align=8 base size=8 base align=8 Derived (0x7ff893479d90) 0 nearly-empty vptr=((& Derived::_ZTV7Derived) + 16u) Base (0x7ff893479e00) 0 nearly-empty primary-for Derived (0x7ff893479d90)
Удаление "чистоты" из f
изменяет пятую строку на:
16 Base::f
Запись vtable будет в базовом классе.
Почему? Потому что у вас может быть тип базового указателя, который содержит адрес объекта производного типа и по-прежнему вызывает метод для переменной-указателя базового типа.
Pure virtual просто сообщает компилятору, что производные типы должны предоставлять свою собственную реализацию, и они не могут полагаться на реализацию базового класса (если она даже указана в базовом классе)
В обоих собственно. Базовый класс vtable будет иметь слот для чистой виртуальной функции, указывающей на что-то вроде заглушки pure_virtual_function_called ()
, которая, вероятно, прервет выполнение программы, в то время как производный класс vtable будет иметь указатель на фактическую реализацию.
Каждый класс имеет свою собственную виртуальную таблицу. Запись для f
в Base
будет NULL
, а запись в Derived
будет указателем на код для реализованного метода. .