先看一个例子:(Win32 VS平台)
第一种情况:
class Base
{public:
virtual void Func1() {};
};
class Derived: public Base
{
public:
virtual void Func2() {};
};
请问,sizeof(Derived)==?
相信这个很多人都可以知道答案4,这里Func1(),Func2()地址都放在Derived的虚函数表中。内存布局如下所示:
Derived 虚函数表指针 4 ----> | Base::Func1() | Derived::Func2() |
如果改成这样:
第二中情况:
class Base
{public:
virtual void Func1() {};
};
class Derived: public virtual Base
{
public:
virtual void Func2() {};
};
只增加了个virtual关键字,sizeof(Derived)等于多少呢?
按照惯性思维,虚继承应该增加一个虚基类指针vbptr,大小在原来的基础上应增加4,为8。
但是在VS上调试却是12。这个就值得我们考虑下了。。。
通过修改编译选项在编译时即可查看内存布局,发现:
虚继承的时候,Func1()函数不在Derived的虚函数表中,而在其基类的虚函数表中。
这里涉及到虚继承的意义,是为了避免二义性。
假设将Func1()放入Derived的虚函数表中,按照此规则,再有一个类(Derived2)继承自Base,那么Func1()会放入Derived2的虚函数表中,
如果有一个类(Triple)继承自Derived和Derived2,那么Triple 的对象调用Func1()该如何调用呢?因为有2个Func1()
从这里我们可以推翻上面的假设。
这个时候编译器做了优化,给Base单独分配一个虚函数表指针。排列顺序是:
Derived 虚函数表指针 4 ----> | Derived::Func2() |
Derived 虚基类指针 4
Base 虚函数表指针 4 ----> | Base::Func1() |