class B
{
public: virtual void fun1() {}
};
class D: public B
{
public: virtual void fun1() {}
};
int main()
{
//Empty Main.
//Not creating any object of B or D.
return 0;
}
在GCC或Visual Studio中,编译器会在此处创建任何vTable吗?
据我所知,它不应创建任何vTable,因为我们没有创建任何B或C obj。因此,我认为无需创建。
我正确吗?
答案 0 :(得分:1)
使用gcc时,会在the translation unit that defines the first non-inline virtual, but not pure virtual, method of the class中发射(创建)一个vtable。这不取决于是否创建了该类的任何对象。 (在您的示例中,没有这样的功能。但是,这似乎并不是您要问的重点,所以我将忽略它。)
不过,链接器可以随意丢弃任何可以证明未使用的东西。因此,即使编译器创建了该vtable,它也可能不会出现在最终可执行文件中。
答案 1 :(得分:1)
试图查看已编译的C ++的程序集输出 在https://godbolt.org/上,编译器为x86-64 gcc9.2
情况1: 链接:https://godbolt.org/z/jFkC4Q
class B
{
public: virtual void fun1() {}
};
class D: public B
{
public: virtual void fun1() {}
};
int main()
{
//Empty Main.
//Not creating any object of B or D.
return 0;
}
以上代码的结果为:
main:
push rbp
mov rbp, rsp
mov eax, 0
pop rbp
ret
情况2: 链接:https://godbolt.org/z/WyNY9j
class B
{
public: virtual void fun1() {}
};
class D: public B
{
public: virtual void fun1() {}
};
int main()
{
//Non Empty Main.
D d; // creating object of D
return 0;
}
以上代码的结果为:
D::fun1():
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
nop
pop rbp
ret
main:
push rbp
mov rbp, rsp
mov eax, OFFSET FLAT:vtable for D+16
mov QWORD PTR [rbp-8], rax
mov eax, 0
pop rbp
ret
vtable for D:
.quad 0
.quad typeinfo for D
.quad D::fun1()
typeinfo for D:
.quad vtable for __cxxabiv1::__si_class_type_info+16
.quad typeinfo name for D
.quad typeinfo for B
typeinfo name for D:
.string "1D"
typeinfo for B:
.quad vtable for __cxxabiv1::__class_type_info+16
.quad typeinfo name for B
typeinfo name for B:
.string "1B"
在第二种情况下,我们可以看到该vtable已创建。
答案 2 :(得分:0)
Vtables是静态数据,非常类似于常量数组。每个(简单)多态类只有一个。 (复杂的类可以有很多vtable,但这是一个细节。)
与其他任何符号一样,它可以由代码引用。如果您不创建类的实例,则不需要它,但是它将由您的类的构造函数引用(但是这些构造函数将是未引用的符号)。
链接器可能会删除不需要的符号。