关于C++派生类同名方法与vtable判断的技术疑问
问题解答
1. 关于“派生类中签名相同的函数默认在父类中是虚函数”的说法是否正确?
这个说法完全错误。在C++中,基类的成员函数不会因为派生类存在签名相同的函数就自动变成虚函数:
- 当基类函数没有显式声明
virtual时,派生类中签名相同的函数只是隐藏(hide)了基类的同名函数,而非重写(override)。此时函数调用是静态绑定,编译器会根据变量的静态类型决定调用哪个函数。 - 只有当基类函数显式标记为
virtual后,派生类中签名相同的函数才会自动成为虚函数(C++11及以后建议显式加override关键字明确重写意图),此时支持动态绑定,函数调用由对象的实际类型决定。
2. 能否通过sizeof()判断父子类体系是否使用虚表(vtable)?
在绝大多数编译器实现中,可以通过sizeof()的变化间接判断类是否包含虚表指针(vptr):
- 当类中存在虚函数(或继承了包含虚函数的基类)时,编译器会为该类实例添加一个虚表指针,用于指向虚函数表(vtable)。这个指针会增加类的大小(32位系统通常+4字节,64位系统通常+8字节)。
- 但需要注意特殊情况:
- 空类(无任何成员)的
sizeof通常为1字节(用于标记对象存在),如果添加虚函数,sizeof会变为指针大小。 - 如果类继承了多个包含虚函数的基类,可能会存在多个虚表指针,
sizeof的增量会对应多个指针的大小。
- 空类(无任何成员)的
结合你的测试代码分析
你的代码中,未给Base::greet()和operator()加virtual时:
Base的大小就是int的大小(通常4字节),Derived的大小是Base的大小+float的大小(通常4+4=8字节),此时没有虚表指针。- 当给
Base的对应函数添加virtual后:Base的大小会增加一个虚表指针的大小(64位系统下变为4+8=12字节),Derived的大小变为12+4=16字节——因为继承了包含虚表指针的基类,自身也会携带这个指针(或共享基类的虚表结构,具体由编译器实现决定,但大小会体现指针的存在)。
内容的提问来源于stack exchange,提问作者Nkyla
相关产品推荐
相关产品推荐

