Я использую VS 2013 и пытаюсь увидеть, как vptr и vftable работают на уровне объекта. Таким образом, у меня есть следующие классы:Как один vtable отслеживает новые виртуальные функции?
#include<iostream>
using namespace std;
class baseClass
{
public:
void nonVirtualFunc() {}
virtual void virtualNonOverriddenFunc() {}
virtual void virtualOverriddenFunc() {}
};
class derivedClass : public baseClass
{
public:
virtual void virtualOverriddenFunc() {}
virtual void derivedClassOnlyVirtualFunc() { cout << "derivedClass" << endl; }
};
int main(int argc, char** argv) {
derivedClass derivedClassObj2;
cout << "Size of derivedClassObj: " << sizeof(derivedClassObj2) << endl;
return 0;
}
И это то, что я вижу при отладке:
Теоретически должно быть ДВА vptrs. Один для vftable baseClass и один для производного класса для отслеживания недавно добавленного метода производного класса ClassClassOnlyVirtualFunc().
Но, как вы видите, есть только один vptr/vftable. Но механизм работает отлично.
Я думал, что есть второй vptr, который я не вижу в окне часов, поэтому я распечатал размер объекта. Это 4 байта, что указывает на наличие только одного указателя.
Как это работает с недавно добавленной виртуальной функцией?
Согласно this должно быть два vptrs.
EDIT: Я проверил содержимое памяти vftable, как предложил Серж, и действительно есть три записи. По какой-то причине он не отображается в отладчике.
Cheers.
Нет, потому что, когда вы создаете производный объект, записи в таблице vtable заменяются адресами виртуальных функций производных (если их переопределить). Это делается во время построения объекта, который объясняет, почему вы не должны называть виртуальные функции в конструкторах/деструкторах. – Borgleader
Почему в объекте должно быть два?Одного достаточно, производные классы vtable основаны на базовых классах, добавляя дополнительные записи для большего количества виртуальных машин и заменяя другие, чтобы указать на новую реализацию. – Deduplicator
@Borgleader: вызов виртуальных функций в ctors и dtors прекрасен. – Deduplicator