我知道菱形继承会导致歧义,可以通过 virtual Base Classes
使用继承来避免,问题不在于它。当类是多态时,问题是关于菱形层次结构中最派生类的大小。这是一个示例代码和示例输出:
#include<iostream>
using namespace std;
class Base
{
public:
virtual void doSomething(){}
};
class Derived1:public virtual Base
{
public:
virtual void doSomething(){}
};
class Derived2:public virtual Base
{
public:
virtual void doSomething(){}
};
class Derived3:public Derived1,public Derived2
{
public:
virtual void doSomething(){}
};
int main()
{
Base obj;
Derived1 objDerived1;
Derived2 objDerived2;
Derived3 objDerived3;
cout<<"\n Size of Base: "<<sizeof(obj);
cout<<"\n Size of Derived1: "<<sizeof(objDerived1);
cout<<"\n Size of Derived2: "<<sizeof(objDerived2);
cout<<"\n Size of Derived3: "<<sizeof(objDerived3);
return 0;
}
我得到的输出是:
Size of Base: 4
Size of Derived1: 4
Size of Derived2: 4
Size of Derived3: 8
据我了解
Base
包含一个虚拟成员函数,因此,sizeof Base = 此环境中 vptr 的大小 = 4
Derived1
和 Derived2
类的情况类似。以下是我与上述场景相关的问题:
Derived3
类对象的大小如何,这是否意味着 Derived3 类有 2 个 vptr?Derived3
类如何与这两个 vptr 一起工作,关于它使用的机制的任何想法?类的大小作为编译器的实现细节而没有被标准定义(因为虚拟机制本身是编译器的实现细节)?
最佳答案
是的,Derived3
有两个 vtable 指针。如果您按值访问它,它会使用 Derived3
版本,或者从父级中选择一个函数,或者如果无法决定则表示它是模棱两可的。
对于子项,它使用与多态使用的父项 1/2 对应的 vtable。
请注意,您没有正确使用虚拟继承:我相信 Derived1 和 2 应该从 Base
虚拟继承。 sizeof(Derived3)
似乎仍然是 8,因为它仍然有两个可能的 parent ,可以被视为 Derived3
。当您转换为父项之一时,编译器实际上会调整对象指针以拥有正确的 vtable。
另外我应该指出,任何与 vtable 相关的东西都是特定于实现的,因为标准中甚至没有提到 vtables。