c++多态对象模型:有虚函数的菱形继承和菱形虚拟继承
程序员文章站
2024-03-22 23:48:04
...
-
-
一:菱形继承
class A
{
public:
virtual void func1()
{
cout << "A::func1()";
}
virtual void func2()
{
cout << "A::func2()";
}
public://这里为public,方便待会赋值查看内存
int _a;
};
class B : public A
{
public:
virtual void func1()
{
cout << "B::func1()";
}
virtual void func3()
{
cout << "B::func3()";
}
public:
int _b;
};
class C : public A
{
public:
virtual void func1()
{
cout << "C::func1()";
}
virtual void func3()
{
cout << "C::func3()";
}
public:
int _c;
};
class D : public B, public C
{
public:
virtual void func1()
{
cout << "D::func1()";
}
virtual void func4()
{
cout << "D::func4()";
}
public:
int _d;
};
它的结构是这样的:
来看他的布局:
void test()
{
D d;
d.B::_a = 1;
d._b = 2;
d.C::_a = 3;
d._c = 4;
d._d = 5;
}
可以看出,B继承了A,B里有A的虚表,C里有A的虚表,然后D继承了B和C,那么D里有两个虚表。
接下来打印地址:
Print((int**)(((int*)&d)));//第一个虚表
可以看到,func4依然是给了第一个虚表。
注:因为清理解决方案导致地址不同,不影响。
这样得到了菱形继承的模型:
二:菱形虚拟继承
class A
{
public:
virtual void func1()
{
cout << "A::func1()";
}
virtual void func2()
{
cout << "A::func2()";
}
public:
int _a;
};
class B : virtual public A//虚拟继承
{
public:
virtual void func1()
{
cout << "B::func1()";
}
virtual void func3()
{
cout << "B::func3()";
}
public:
int _b;
};
class C : virtual public A//虚拟继承
{
public:
virtual void func1()
{
cout << "C::func1()";
}
virtual void func3()
{
cout << "C::func3()";
}
public:
int _c;
};
class D : public B, public C
{
public:
virtual void func1()
{
cout << "D::func1()";
}
virtual void func4()
{
cout << "D::func4()";
}
public:
int _d;
};
结构变化不大,就是多了虚拟继承,那么再来看看布局:
void test()
{
D d1;
d1.B::_a = 1;
d1._b = 2;
d1.C::_a = 3;
d1._c = 4;
d1._d = 5;
}
好像看不出来什么,好复杂的感觉。
来看内存:
因为已经对数据成员赋值,所以看的能清楚一些,蓝色框起来的三个是属于B,桔色框起来三个属于C,紫色框起来三个属于A,接下来我用到打印函数。
Print((int**)(*((int**)&d1)));
Print((int**)(*((int**)((char*)&d1 + 12))));
Print((int**)(*((int**)( (char*)&d1+28 ))));
可以看到,B的虚表存了B的func3和D的func4,C的虚表存了C的func3,A的虚表存了D的func1和A的func2。
之前有文章写了菱形继承,虚拟继承解决了二义性和数据冗余,由于D同时继承了B和C,B和C又分别继承了A,所以D里面会有两份A,所以加上虚拟继承,A会在最下面。
至于虚机表指针:
这里分别是B和C的虚机表,第一行是-4的意思,表示和虚表的地址差4字节,若没有虚表存在,就会存0。
(ff ff ff ff是-1,顺着推也能得到ff ff ff fc是-4)
第二行是距离A的步数,B离A24字节,C离A12字节。
所以得到了对象模型:
上一篇: C++对象模型:单继承,多继承,虚继承
下一篇: Mac:启动mongodb失败