我在stackoverflow中看到了几个显示vtable概念的例子,但是给出的示例仅针对单个类,当我们从两个抽象类派生类时,那么将为该类创建多少个vtable?
class A {
public :
virtual void func_1() = 0;
};
class B {
public :
virtual void func_2() = 0;
};
class C : public A, public B {
public :
void func_1()
{
cout << "func_1" << endl;
}
void func_2()
{
cout << "func_2" << endl;
};
在上面的示例中,C类有多少个vtable,A类和B类是否有任何vtable?
答案 0 :(得分:4)
在这种特定情况下,C有一个vtable而A和B没有。您可以通过不正常的C&#39成员函数自己看到这一点,以便实际发出vtable,并纠正其他编译错误:
extern "C" int puts(const char *);
struct A { virtual void func_1() = 0; };
struct B { virtual void func_2() = 0; };
struct C : A, B
{
void func_1();
void func_2();
};
void C::func_1() { puts("func_1"); }
void C::func_2() { puts("func_2"); }
...编译到目标文件,然后查看符号:
$ gcc -c test.cc
$ nm test.o | c++filt
U puts
0000000000000000 T C::func_1()
000000000000001a T C::func_2()
0000000000000033 T non-virtual thunk to C::func_2()
0000000000000000 V typeinfo for A
0000000000000000 V typeinfo for B
0000000000000000 V typeinfo for C
0000000000000000 V typeinfo name for A
0000000000000000 V typeinfo name for B
0000000000000000 V typeinfo name for C
0000000000000000 V vtable for C
U vtable for __cxxabiv1::__class_type_info
U vtable for __cxxabiv1::__vmi_class_type_info
编译器可以证明只有C的基本vtable是必要的,因为没有类具有数据或非平凡构造函数,并且因为A和B不能直接实例化。在一般情况下,所有三个类可能有多个vtable。何时需要多个vtable的确切规则非常复杂,我不打算在这里总结它们。它们在"Itanium" C++ ABI第2.5和2.6节中有详细说明,但如果您不习惯阅读标准和,那么它们可能不会有多大意义。 C ++的黑暗角落;不幸的是,我不知道对初学者有任何好的概述。 (历史上一直认为你要么不关心,要么你已经是专家了。)(&#34; Itanium&#34;上面引用了引号,因为规范是写的考虑到Itanium,但设计被广泛采用。除非你使用MSVC,否则你可能会得到这个C ++ ABI。)(为了说明这些黑暗角落有多黑暗:我帮助写这个ABI规范,但我并不知道为什么GCC认为它需要向C :: func_2&#34;发出一个非虚拟的thunk。)
答案 1 :(得分:1)
唯一可以确定的方法是编译并查看,但在这种情况下,它确实只有1个vtable(如果你不导出该类,甚至可能为0) 。如果任何一个基类都不抽象,那么答案会因编译器而异。