Когда я строю, разбираю и очищаю эту короткую программу:
struct Base {
virtual int compute() { return 42; }
};
struct Derived: public Base {
int compute() override { return 23; }
};
int main() {
Base* a = new Derived;
a->compute();
}
Что я делаю с некоторой домашней магией:
g++ -g -o- -S foo.cpp | \
c++filt | \
perl -pe 's/^\.LA\w+:\r?\n//gm' | \
perl -0777 -pe 's/^\.Ldebug\w+:\r?\n(\s+\..+?\r?\n)+//gm' | \
perl -pe 's/^\.L\w+:\r?\n//gm' | \
perl -pe 's/^\s+\.(align|section|weak|loc|file|cfi).+\r?\n//gm' | \
highlight --out-format=ansi --syntax=asm
Я получаю это:
vtable for Derived:
.quad 0
.quad typeinfo for Derived
.quad Derived::compute()
.type vtable for Base, @object
.size vtable for Base, 24
vtable for Base:
.quad 0
.quad typeinfo for Base
.quad Base::compute()
.type typeinfo for Derived, @object
.size typeinfo for Derived, 24
Я заметил, что мой vtable
имеет следующую структуру:
0. ???
1. Pointer to typeinfo
2. Pointer to first virtual method
3. Pointer to second virtual method
4. ...
Я не понял, что было 0
в vtable[0]
, но после обнаружения этого другого ТАК вопрос, я написал другой пример, чтобы понять это смещение наверх вещь.
https://godbolt.org/z/eWScPK
Этот использует виртуальное наследование.
struct Top {
virtual void foo() { }
};
struct Left: public Top { // note: non virtual
void foo() override { }
};
struct Right: virtual public Top {
void foo() override { }
};
// note: Bottom is not a "diamond", Top is base twice
struct Bottom: public Left, public Right {
void foo() override { }
};
int main() {
Bottom bottom;
bottom.foo();
}
На этот раз мой vtable
выглядит так:
vtable for Bottom:
.word 4
.word 0
.word typeinfo for Bottom
.word Bottom::foo()
.word 0
.word -4
.word -4
.word typeinfo for Bottom
.word non-virtual thunk to Bottom::foo()
ИтакЯ могу объяснить первый 0
, который стал 4
, но я все еще не в состоянии объяснить новую структуру моего vtable.
Я ищу более подробный ответ, который объяснил бы этот последний пример.