考虑以下代码:
#include <iostream>
#include <typeinfo>
#include <type_traits>
using namespace std;
struct A { int data; };
struct B1 : A {};
struct B2 : virtual A {};
struct Base1 : virtual A {};
struct Base2 : virtual A {};
struct Derived : Base1, Base2 {};
int main() {
cout << sizeof(B1) << endl;
cout << sizeof(B2) << endl;
cout << sizeof(Derived) << endl;
cout << std::is_polymorphic<B1>::value << endl;
cout << std::is_polymorphic<B2>::value << endl;
cout << std::is_polymorphic<Derived>::value << endl;
return 0;
}
在我的系统上它打印
4
8
12
0
0
0
这意味着这些类都不是多态的。然而,B1 和 B2 的大小因指针的大小而不同,该指针可能是指向 vtable 的指针。我运行过 gcc-fdump-class-hierarchy
并得到:
Vtable for B2
B2::_ZTV2B2: 3u entries
0 4u
4 (int (*)(...))0
8 (int (*)(...))(& _ZTI2B2)
VTT for B2
B2::_ZTT2B2: 1u entries
0 ((& B2::_ZTV2B2) + 12u)
Class B2
size=8 align=4
base size=4 base align=4
B2 (0x0x3ca5400) 0 nearly-empty
vptridx=0u vptr=((& B2::_ZTV2B2) + 12u)
A (0x0x3c972d8) 4 virtual
vbaseoffset=-12
这里有一个问题:什么是多态类? “具有 vtable”是否意味着“多态并具有 RTTI”,反之亦然?如果不是,为什么它必须至少有一个虚函数才能成为多态,如果它无论如何都会有 vtable 的话?
看起来多态类的定义与“具有 vtable 的类”不同,因为,正如我们在上面看到的,B2 不是多态类,但具有 vtable,并且正如我认为的那样,应该具有 RTTI。在this http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1529.html#1.2.4.1文档中明确指出“多态 - 即至少有一个虚函数。(这是允许生成的调度代码在类上使用 RTTI 所必需的。)”。
您在这里错过了一个细节:虚拟表是一个实施细节。因此:
- 该标准定义了多态性类作为可以在多态意义上使用的类:即,行为可以被重写
- 编译器使用虚拟表来实现标准规定的一些功能/行为,其中恰好包括多态类和虚拟基。
Thus, yes我知道的编译器(MSVC 和那些遵循 Itanium ABI 的编译器,例如 gcc、icc 和 Clang)将使用虚拟表来提供必要的 RTTIdynamic_cast
在存在虚拟基的情况下工作...不,这与类是否多态无关。
然而,在切线上,更喜欢组合而不是继承意味着如果没有可以重写的行为,就没有理由从类继承。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)