下面的代码是多重继承,每个类都有一个成员变量、一个普通函数和一个虚函数。
程序的输出结果如下:
我们可以看到,在基类“basec”和每个虚拟派生类“derivedc”和“derivedd”的对象中都添加了一个vptr用于它们的vtable。
问题是,为什么子类即使有虚函数也没有自己的vtable,并且在其对象中也没有自己的vptr? 在哪个类的vtable中会出现子类的虚函数?
class basec
{
int x;
public:
basec()
{
x = 0;
}
void print()
{}
virtual void xyz()
{}
};
class derivedc: public virtual basec
{
int dc;
public:
derivedc()
{
dc = 0;
}
virtual void xyzdc()
{}
};
class derivedd: public virtual basec
{
int dd;
public:
derivedd()
{
dd = 0;
}
virtual void xyzdd()
{}
};
class child: public derivedc, public derivedd
{
char de;
public:
child()
{
de = '4';
}
virtual void xyzde()
{}
};
main(int argc, char **argv)
{
basec bobj, bobjc;
derivedc dcobj;
derivedd ddobj;
child deobj;
std::cout << "C " << sizeof(basec) << endl;
std::cout << "D " << sizeof(derivedc) << endl;
std::cout << "E " << sizeof(derivedd) << endl;
std::cout << "F " << sizeof(child) << endl;
return(0);
}
程序的输出结果如下:
main()
C 8
D 16
E 16
F 28
在gdb中查看每个对象,我看到以下内容:
(gdb) p/x bobj
$1 = {_vptr.basec = 0x8048c80, x = 0x0}
(gdb) p/x dcobj
$3 = {<basec> = {_vptr.basec = 0x8048c5c, x = 0x0}, _vptr.derivedc = 0x8048c4c, dc = 0x0}
(gdb) p/x ddobj
$4 = {<basec> = {_vptr.basec = 0x8048c1c, x = 0x0}, _vptr.derivedd = 0x8048c0c, dd = 0x0}
(gdb) p/x deobj
$5 = {<derivedc> = {<basec> = {_vptr.basec = 0x8048b90, x = 0x0}, _vptr.derivedc = 0x8048b6c, dc = 0x0}, <derivedd> = {_vptr.derivedd = 0x8048b80, dd = 0x0}, de = 0x34}
我们可以看到,在基类“basec”和每个虚拟派生类“derivedc”和“derivedd”的对象中都添加了一个vptr用于它们的vtable。
问题是,为什么子类即使有虚函数也没有自己的vtable,并且在其对象中也没有自己的vptr? 在哪个类的vtable中会出现子类的虚函数?
child :: xyzde()
放在derivedc
中的vtable中,在子类中查看“ child的vtable”-https://gcc.godbolt.org/z/d2VWza。如果您将`child`更改为`class child:public virtual derivedc,public virtual derivedd,则会得到三个单独的表格。 https://gcc.godbolt.org/z/wCbmWb。如果您删除所有
virtual继承,则会按预期复制
basec` -https://gcc.godbolt.org/z/8wxPGA。 - Mihayl0x8048b90
、0x8048b6c
和0x8048b80
。它只是没有自己的vptr,因为那完全是多余的。 - Sebastian Redl