Itanium C++ ABI VTT содержание
Я читал о структуре VTT отсюда(2.6.2). Однако я не понимаю цели всех присутствующих элементов.
Первичный виртуальный указатель должен указывать на первичную виртуальную таблицу D (в группе vtable, верно?)
Вторичные VTT содержат VTT, которые передаются прямым невиртуальным базовым классам (назовем их B) при их создании. Насколько я понимаю, поскольку эти прямые базовые классы (B) могут наследоваться от виртуальных классов, эти прямые базовые классы (B) должны дать этим уже инициализированным виртуальным классам некоторую другую vtable, чтобы "заставить их поверить", что они являются только частью каждого B. Это правильно?
Теперь, какова цель последних 2 типов записей: вторичные виртуальные указатели и виртуальные VTT? Я понимаю, что виртуальные классы в иерархии наследования не получили надлежащую итоговую таблицу, поэтому это может быть одной из целей. Кроме того, виртуальные классы могут наследовать себя от других виртуальных классов (учтите, что V1 наследуется от V2). Затем V2 снова нужен специальный vtable, чтобы "заставить его поверить", что он является частью V1 (когда конструируется V1).
Я был бы признателен, если бы вы могли объяснить точное содержание и цель каждого типа записи в VTT.
1 ответ
Подстановочность Лискова означает, что производный класс должен использоваться везде, где базовый класс будет приемлемым. В C++ это означает, что вы можете передать адрес Derived
объект функции, которая принимает Base*
,
Теперь при строительстве сложного объекта может возникнуть ситуация, когда *this
такой производный объект по правилам C++ (как Derived
ctor успешно запустился), и поэтому вы должны быть в состоянии пройти *this
к функции, ожидающей Base*
,
Но при множественном и виртуальном наследовании вам нужны дополнительные меры предосторожности. Base*
должен указать на Base
субобъект. А в Itanium ABI этот базовый подобъект должен иметь указатель vtable, который правильно описывает поведение частично созданного объекта. Это поведение зависит от того, какие именно детали есть, а какие нет.
В то время как объект может быть частично построен, гранулярность этого - только уровень класса. Наиболее производный вызываемый конструктор определяет, какие именно конструкторы базового класса будут выполняться (это не зависит от поведения во время выполнения). И каждый из них либо бежал, либо нет.
Следовательно, жизнеспособная реализация должна иметь набор vtables и набор указателей vtable в каждом подобъекте базового класса (возможно, перекрывающихся) и устанавливать указатели vtable по мере успешного завершения каждого конструктора.
Виртуальные базовые классы явно не связаны с виртуальными функциями, но получили свое название из-за того, что вы можете хранить смещения виртуальных базовых классов в vtables. Это смещение необходимо при прохождении Derived* this
к функции, принимающей Base*
, где это Base
Тип является виртуальным базовым классом Derived
, (Вы бы использовали фиксированное смещение, когда это обычный базовый класс, и это смещение может быть даже нулевым)