c++ vtable в множественном наследовании, указатель на метод thunk

Я прочитал эту статью: https://shaharmike.com/cpp/vtable-part2/

И я не могу понять, почему в vtable (в конце статьи) у нас есть этот указатель:

0x400918 0x400820 невиртуальный переход к Child::FatherFoo()

но не указатель непосредственно на метод Child::FatherFoo()?

Я предполагаю, что vtable Child полностью отделена от vtable отца.


person Łukasz Ciałoń    schedule 26.02.2018    source источник
comment
Статья очень хорошо объясняет это, я думаю, Here’s the solution: the compiler creates a ‘thunk’ method that corrects this and then calls the ‘real’ method. The address of the thunk method will sit under Child’s Father vtable, while the ‘real’ method will be under Child’s vtable. Это также играет роль в этом предложении In other words, for a given Child c;: (void*)&c != (void*)static_cast<Father*>(&c), которое показывает вам, почему указатель this должен быть скорректирован.   -  person PeterT    schedule 27.02.2018
comment
при доступе к FatherFool() через Отец* этот указатель указывает на вторую виртуальную таблицу в примере. Преобразователь в основном используется для настройки этого указателя на самый верх объекта, это критический шаг, потому что отображение Child::FatherFoo() может получить доступ к элементу данных в Mother или Child.   -  person xwang    schedule 03.07.2019


Ответы (1)


Точно так же, как все члены структуры C, кроме одного, не могут иметь тот же адрес, что и охватывающий объект, все непустые подобъекты базового класса, кроме одного, не могут иметь тот же адрес, что и полный объект; полиморфный базовый класс (с виртуальными функциями) не является пустым по определению.

Полиморфный базовый подобъект, имеющий тот же адрес, что и производный объект, называется первичным базовым. Производный объект разделяет основу макета vtable и vptr с первичной базой: неявный параметр this не изменяется.

Примечание. Концепция первичной базы — это концепция домена реализации C++ (например, vtable, vptr...), а не концепция языка C++ (например, базовый класс, виртуальная функция...). Так что, очевидно, это не описано в стандарте C++.

Когда виртуальная функция вызывается динамически через механизм виртуального вызова для объекта неизвестного динамического типа, неявный аргумент this должен быть настроен на правильное значение, которое является другим значением не первичных баз. Посредник, который это делает, называется преобразователь. В этом случае преобразователь может сделать переход, а не вызов функции, к правильной функции: дополнительная работа выполняется при входе в функцию, и ничего не требуется при выходе из функции.

Другой тип корректировки возникает, когда используется ковариантный тип возвращаемого значения, а производное отношение ковариантного возврата к базовому не является отношением производного к первичному базовому. Очевидно, что этот тип преобразователя не выполняет переход, он выполняет вызов функции, поскольку корректировка ковариации происходит при выходе из функции.

person curiousguy    schedule 01.03.2018