继承体系下派生类的对象模型

      上一篇中我们一起探索了继承的权限问题https://blog.csdn.net/a15929748502/article/details/80796483,这一篇我们来一起探索继承体系下派生类的对象模型是什么样的呢?

首先什么是对象模型呢,对象模型就是对象中非静态成员变量在内存中的布局

1.下面我们就从最简单的单继承开始研究,

什么是单继承呢,简单地说就是一个派生类只有一个父类

码出如下代码

#include <iostream>
using namespace   std;

class Base        //基类
{
public:
        int _b;

};
class Derived :public Base        //继承
{
public:
        int _d;

};
int main()
{
        Derived   d;
        d._b=1;
        d._d=2;
        cout<<*((int*)&d)<<endl;                  //打印出模型中的第一个元素
        cout<<*((int*)&d+1)<<endl;                //打印出模型中的第二个元素
        cout << sizeof(Base) << endl;             //4
        cout << sizeof(Derived) << endl;          //8
        return 0;
}

编译后打印出的结果为

[root@localhost C++]# ./a.out
1
2
4
8

可以说明

D的对象模型中,基类成员在上+派生类自己的成员在下

D大小为8个字节,基类成员大小加上派生类成员大小

编译器没有为派生类合成构造函数

图示为


2.多继承

什么是多继承呢,简单的来说就是一个派生类有多个父类

include <iostream>
using namespace   std;

class Base1        //基类
{
public:
        int _b1;

};

class Base2        //基类
{
public:
        int _b2;

};

class Derived :public Base1,public Base2        //继承
{
public:
        int _d;

};
int main()
{
        Derived   d;
        d._b1=1;
        d._b2=2;
        d._d=3;
        cout<<*((int*)&d)<<endl;
        cout<<*((int*)&d+1)<<endl;
        cout<<*((int*)&d+2)<<endl;
        cout << sizeof(Base1) << endl;             //4
        cout << sizeof(Base2) << endl;             //4
        cout << sizeof(Derived) << endl;          //12
        return 0;
}

打印结果是

[root@localhost C++]# ./a.out
1
2
3
4
4
12

可以看出多继承与单继承对象模型类似基类成员在上+派生类自己的成员在下


D大小基类成员大小加上派生类成员大小。

读者可以自行验证

3.菱形继承

菱形就比较复杂了,这里我画了一个示意图希望可以帮大家理解


这样看简单的来说,菱形继承就是一个先单继承,再多继承的过程

我们可以码出如下代码

#include <iostream>
using   namespace    std
class B
{
        public:
                int _b;
};
class C1: public B
{
        public:
                int _c1;
};
class C2 : public B
{
        public:
                int _c2;
};
class D : public C1, public C2
{
        public:
                int _d;
};

int main()
{
        D  d;
        d._b=1;
        d._c1=2;
        d._c2=3;
        d._d=4;
        cout<<*((int*)&d)<<endl;
        cout<<*((int*)&d+1)<<endl;
        cout<<*((int*)&d+2)<<endl;
        cout<<*((int*)&d+3)<<endl;

        cout << sizeof(B) << endl;       //4
        cout << sizeof(C1) << endl;      //8
        cout << sizeof(C2) << endl;      //8            
        cout << sizeof(D) << endl;       //20
        return 0;
}

这段代码看起来是没有问题的,但是在编译时就发生了错吴

C1++.cpp:27: error: request for member ‘_b’ is ambiguous
C1++.cpp:6: error: candidates are: int B::_b
C1++.cpp:6: error:                 int B::_b

编译器不可以确定是哪一个,下面我将对代码进行修改(在主函数中)

int main()
{
        D  d;
        d.C1::_b=1;
        d.C2::_b=2;
        d._c1=3;
        d._c2=4;
        d._d=5;
        cout<<*((int*)&d)<<endl;
        cout<<*((int*)&d+1)<<endl;
        cout<<*((int*)&d+2)<<endl;
        cout<<*((int*)&d+3)<<endl;
        cout<<*((int*)&d+4)<<endl;

        cout << sizeof(B) << endl;       //4
        cout << sizeof(C1) << endl;      //8
        cout << sizeof(C2) << endl;      //8            
        cout << sizeof(D) << endl;       //20
        return 0;
}

这次就可以通过了,打印的结果是

[root@localhost C++]# ./a.out
1
3
2
4
5
4
8
8
20

由此我们可以看出D的对象模型


大小为20个字节

基类的成员变量在派生类中存了两份

这显然是不合理的,那么应该怎样解决呢,下一篇虚拟继承我会和大家继续探讨的




猜你喜欢

转载自blog.csdn.net/a15929748502/article/details/80893870