• 继承的内存构造



    对于单继承而言,对象的地址固定


    #include 
    
    using namespace std;
    
    class Parent
    {
    public:
        int mi;
    
        void print()
        {
            cout << this << endl;
        }
    };
    
    class Child : public Parent
    {
    public:
        int mv;
    
        void print()
        {
            cout << this << endl;
        }
    };
    
    int main()
    {
        Parent p;
        Child c;
    
        p.mi = 3;
        c.mv = 2;
        c.mi = 1;
    
        cout << &p.mi << endl;
        cout << &(c.mv) << endl;
        cout << &(c.mi) << endl << endl;
    
        int* p0 = (int*)0x61feb0;
        int* p1 = (int*)0x61feac;
        int* p2 = (int*)0x61fea8;
    
        cout << *p0 << endl;
        cout << *p1 << endl;
        cout << *p2 << endl << endl;
    
        cout << &c << endl;
        c.print();
        c.Parent::print();
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    在这里插入图片描述

    所以,继承的内存构造为:(对于栈来讲,它的生长方式是向下的,是向着内存地址减小的方向增长。)
    在这里插入图片描述

    对于单继承而言,内部包含了继承而来的变量和自己的变量,也可以调用父类中的成员函数和自己的成员函数,当子类对象调用这些成员函数时,函数的 this 指针指向子类对象的地址。

    对象的地址就是自身首个成员变量的存储地址。

    可以这样理解:
    子类的成员变量 = 父类的成员变量(有访问权限) + 子类自己的成员变量
    子类的成员函数 = 父类的成员函数 + 子类自己的成员函数


    对于多继承而言,会出现同一个对象的地址不同的情况。


    #include 
    #include 
    using namespace std;
    
    class BaseA
    {
        int ma;
    public:
        BaseA(int a)
        {
            ma = a;
        }
        int getA()
        {
            return ma;
        }
    };
    
    class BaseB
    {
        int mb;
    public:
        BaseB(int b)
        {
            mb = b;
        }
    
        int getB()
        {
            return mb;
        }
    
        void print()
        {
            cout << this << endl;
        }
    };
    
    class Derived : public BaseA , public BaseB
    {
        int mc;
    public:
        Derived(int a, int b, int c):BaseA(a),BaseB(b)
        {
            mc = c;
        }
        int getC()
        {
            return mc;
        }
    
        void print()
        {
            cout << this << endl;
        }
    };
    
    int main()
    {
        cout << "sizeof(Derived) = " << sizeof(Derived) << endl;
        Derived d(1, 2, 3);
    
        BaseA* pa = &d;
        BaseB* pb = &d;
    
        cout << "&d = " << &d << endl;
        cout << "pa = " << pa << endl;
        cout << "pb = " << pb << endl << endl;
    
        d.print();
        d.BaseB::print();
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    在这里插入图片描述

    当子类对象继承了两个父类对象,从图中程序可知,多继承会导致同一个对象出现多个对象地址。


    工程中的单继承加多接口情形:

    #include 
    
    using namespace std;
    
    class Demo
    {
    protected:
        int mi;
    public:
        Demo(int i)
        {
            mi = i;
            cout << "this = " << this << endl;
        }
    
        void print()
        {
            cout << this << endl;
        }
    
        bool equal(Demo* p)
        {
            cout << p << endl;
            cout << this << endl;
            return p == this;
        }
    };
    
    class Interface1
    {
    public:
        virtual void add(int n) = 0;
    };
    
    class Interface2
    {
    public:
        virtual void minus(int n) = 0;
    };
    
    class Interface3
    {
    public:
        virtual void multiply(int n) = 0;
    };
    
    class Derived : public Demo, public Interface1, public Interface2, public Interface3
    {
    public:
        Derived(int i):Demo(i)
        {
    
        }
        void add(int n)
        {
            mi += n;
        }
    
        void minus(int n)
        {
            mi -= n;
        }
    
        void multiply(int n)
        {
            mi *= n;
        }
    
        void print()
        {
            cout << this << endl;
        }
    };
    
    int main()
    {
        Derived d(100);
        cout << sizeof(d) << endl << endl;
    
        Demo* demo = &d;
        Interface1* p1 = &d;
        Interface2* p2 = &d;
        Interface3* p3 = &d;
    
        p1->add(10);
        p2->minus(100);
        p3->multiply(3);
    
        cout << "&d = " << &d << endl;
        d.Demo::print();
        d.print();
    
        cout << endl;
    
        cout << demo << endl;
        cout << p1 << endl;
        cout << p2 << endl;
        cout << p3 << endl << endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101

    单继承加多接口情形也会出现多个对象地址,但是通过 dynamic_cast 可以将内部的接口指针其转化成单继承指针。

    我个人觉得出现多个对象地址是为了更好的划分内部不同父对象的区域,其实也是内部从父类继承而来的成员变量的地址。


    定义一个普通类 Test,在主函数中它只能通过定义对象来调用成员函数;
    如果成员函数 func() 是静态成员函数,那么在主函数中可以通过 Test::func()来调用静态成员函数。

    如果两个类 class Parent 和 class Child 是继承关系,那么可以在 Child 类的成员函数中通过作用域分辨符来调用父类的成员函数。

    #include 
    using namespace std;
    
    class Parent
    {
    public:
        int get() 
        {
            return 2;
        }
        
        void print()
        {
            cout << "xiebs" << endl;
        }
    };
    
    class Child : public Parent
    {
    public:
        void print() 
        {
            int i = Parent::get();
            cout << "xiebs" << endl;
        }
    };
    
    int main()
    {
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在这里插入图片描述

    因为模板分为两次编译过程,第一次编译的时候会忽略掉依赖模板参数的名字,所以继承的父类在第一次编译被忽略,所以父类的成员就会被忽略。在子类模板定义的域内就找不到名字的声明,所以会直接报错

  • 相关阅读:
    uCOSIII实时操作系统 十一 消息传递
    C/C++图的最小生成树和最短路径的实践
    小节8:Python之文件操作
    Node 安装 Vuex
    Java声明式事务实战!工作中用这几种就够了!
    Java新特性Stream流详解
    orangepi 香橙派-实时时钟模块使用DS1307/DS3231/PCF8563
    C语言实现windows,linux双版本下的进度条小程序,快来试一试吧
    【雷达原理】雷达测距原理及实现方法
    基于C#实现协同推荐 SlopeOne 算法
  • 原文地址:https://blog.csdn.net/xiebs/article/details/127860284