C++多态分析

struct A
{
    int a=1;
};
struct B:A
{
    int b=2;
};
struct C:A
{
    int c=3;
};
struct D:B,C
{
    int d=4;
};
int main()
{
    D d;
//d.a = 1; std::cout
<< sizeof(d) << endl;//20 }

菱形继承:基类有两个子类,有一个类继承了这两个基类的子类,就形成了菱形继承。这样继承会导致d类继承过来的字段冗余,B类会继承父类a字段构造后会拥有ab字段,C类会拥有ac字段,D类继承bc类会有abacd五个字段。当我们给a字段赋值时,将会报a不明确的错误,因为d对象有两个a字段。

分析完毕接下来看汇编:

 进入D类的构造函数,进入构造会传入该类的首地址,根据首地址查找到该类在内存的地址,都是cc。

构造自身前会先call的是B类的构造。

 call完A的构造B类的内存地址已经改变,1已经被赋值进内存。

 在构造里B类构造里把b字段初始化为

 

初始化构造后d对象的内存分布就是有12134这四个字段。

 

解决方案:虚继承

struct A
{
    int a=1;
};
struct B: virtual A
{
    int b=2;
};
struct C:virtual A
{
    int c=3;
};
struct D:B,C
{
    int d=4;
};
int main()
{
    D d;
    d.a = 1;
    std::cout << sizeof(d) << endl;//48
}

内存地址分布:

 

 会包含两张虚表,啷个父类字段,一个基类字段,一个自身字段,虚表里存了28和18。我们计算一下第一张虚表和基类字段a的地址差和第二张虚表与字段a的地址差,会发现刚好是28和18,所以虚表里存的数值是基类字段和虚表的内存差,可以根据值寻找到共享字段的内存地址。

posted @ 2021-10-11 14:14  过往云烟吧  阅读(105)  评论(0)    收藏  举报