C++多继承的情况下派生类如果有N个含虚函数的基类,则派生类对象中会有几个虚表指针,1 还是N ?
N个
下面是一个简单的例子。
struct A {
virtual void f() {}
};
struct B {
virtual void g() {}
};
struct C : public A, public B {
C() {}
virtual void f() {}
virtual void h() {}
};
int main()
{
C c;
}
这是g++生成的汇编代码,可以看出C对象有两个虚表指针
A::f():
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
nop
pop rbp
ret
B::g():
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
nop
pop rbp
ret
A::A() [base object constructor]:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov edx, OFFSET FLAT:vtable for A+16
mov rax, QWORD PTR [rbp-8]
mov QWORD PTR [rax], rdx
nop
pop rbp
ret
B::B() [base object constructor]:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov edx, OFFSET FLAT:vtable for B+16
mov rax, QWORD PTR [rbp-8]
mov QWORD PTR [rax], rdx
nop
pop rbp
ret
C::C() [base object constructor]:
push rbp
mov rbp, rsp
sub rsp, 16
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
mov rdi, rax
call A::A() [base object constructor]
mov rax, QWORD PTR [rbp-8]
add rax, 8
mov rdi, rax
call B::B() [base object constructor]
mov edx, OFFSET FLAT:vtable for C+16
mov rax, QWORD PTR [rbp-8]
mov QWORD PTR [rax], rdx
mov edx, OFFSET FLAT:vtable for C+48
mov rax, QWORD PTR [rbp-8]
mov QWORD PTR [rax+8], rdx
nop
leave
ret
C::f():
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
nop
pop rbp
ret
C::h():
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
nop
pop rbp
ret
main:
push rbp
mov rbp, rsp
sub rsp, 16
lea rax, [rbp-16]
mov rdi, rax
call C::C() [complete object constructor]
mov eax, 0
leave
ret
vtable for C:
.quad 0
.quad typeinfo for C
.quad C::f()
.quad C::h()
.quad -8
.quad typeinfo for C
.quad B::g()
vtable for B:
.quad 0
.quad typeinfo for B
.quad B::g()
vtable for A:
.quad 0
.quad typeinfo for A
.quad A::f()
typeinfo for C:
.quad vtable for __cxxabiv1::__vmi_class_type_info+16
.quad typeinfo name for C
.long 0
.long 2
.quad typeinfo for A
.quad 2
.quad typeinfo for B
.quad 2050
typeinfo name for C:
.string "1C"
typeinfo for B:
.quad vtable for __cxxabiv1::__class_type_info+16
.quad typeinfo name for B
typeinfo name for B:
.string "1B"
typeinfo for A:
.quad vtable for __cxxabiv1::__class_type_info+16
.quad typeinfo name for A
typeinfo name for A:
.string "1A"