Во-первых, vtables никоим образом не являются частью языка C++, а скорее деталью реализации, используемой конкретными компиляторами. Ниже я описываю один из способов, который обычно используется как таковой.
Во-вторых, ваша функция hello
не является виртуальной. Чтобы сделать его виртуальным, вы просто предварительно предварите объявление virtual
.
Предполагая, что он теперь виртуальный: ваша догадка довольно близка. Фактически, vtable
(к которому указатель хранится с каждым экземпляром виртуального класса) представляет собой массив указателей функций. То, как определенная функция просматривается в ней, - это ее порядковый номер. Первая объявленная виртуальная функция в A
- первая запись в ее vtable
, вторая - вторая запись и так далее. Если A
имел базовый класс, индекс первой (не переопределенной) виртуальной функции A
в таблице был бы n+1
, где n
- это индекс последней виртуальной функции его базового класса. Если A
имеет более одного базового класса, их записи предшествуют записям A
в порядке их объявления в качестве базовых классов A
.
Если A
использует виртуальное наследование, изображение немного сложнее, я не буду разбираться, если вы специально не заинтересованы.
ОБНОВЛЕНИЕ: Я добавлю краткое описание для случая виртуального наследования по запросу. Если A
имеет Base
как виртуальный базовый класс, A
в vtable
будет хранить в самом начале (перед адресами функции) смещение байта, где данные Base
начинаются с объекта A
. Это необходимо, потому что, в отличие от обычного наследования, базовый класс не имеет своих данных, предшествующих данным производного класса, вместо этого он следует за ним. Таким образом, любой вызов функции виртуальной функции, определенный в Base
, должен иметь смещение указателя this
на эту сумму. Кроме того, Base
должен иметь свой собственный указатель vtable
, прямо в начале своих данных, где он ожидает его найти. Таким образом, полный объект A
будет содержать два указателя vtable
вместо одного. Фактический vtable
, на который указывает этот второй указатель, будет таким же, как первый указатель vtable
, за исключением расширенного, чтобы пропустить запись смещения, описанную выше (так что любой код Base
с использованием vtable
найдет первую виртуальную функцию в начале, где она ожидается). Помимо этих различий, сам vtable
такой же, как и раньше.
'A :: hello()' не является виртуальной функцией. – tkausl
Нет виртуальных функций и, следовательно, нет vtable в коде, который вы показываете. –
Я знаю.если это виртуальная функция, как она будет оцениваться? –