• C++基础——继承


    1 概述

    继承是面型对象的三大特征之一
    继承用于描述类于类之间的从属关系,被继承的类称为基类或父类,继承的类称为子类

    2 继承的基本语法

    #include 
    using namespace std;
    
    class Father {
    public:
        int getNum() {
            return m_num;
        }
    public:
        int m_num = 10;
    };
    
    class Son :public Father {
    
    };
    
    int main() {
        Son son;
        cout << son.m_num << endl;
        cout << son.getNum() << 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

    输出

    10
    10
    
    • 1
    • 2

    继承之后,子类拥有了父类的属性和行为。需要注意的是,子类是否拥有父类的属性和行为,还决定于继承方式和父类的访问权限。

    3 继承方式

    继承访问分为三种

    • 公共继承
    • 保护继承
    • 私有继承

    语法
    class 子类 :继承方式 父类

    #include 
    
    using namespace std;
    
    class Father {
    private:
        int m_A;
    protected:
        int m_B;
    public:
        int m_C;
    };
    
    void test() {
        Father father;
        // father.m_A; //不能访问private成员
        // father.m_B; //不能访问protected成员
        father.m_C;
    }
    
    // 公共继承
    class Son1 : public Father {
    public:
        void func() {
            // m_A; //不可访问private成员
            m_B;
            m_C;
        }
    };
    
    void test1() {
        Son1 son;
        // son.m_A; //不可访问private成员
        // son.m_B; //不可访问protected成员
        son.m_C;
    }
    
    // 保护继承
    class Son2 : protected Father {
    public:
        void func() {
            // m_A; //不可访问private成员
            m_B;
            m_C;
        }
    };
    
    void test2() {
        Son2 son;
        // son.m_A; //不可访问private成员
        // son.m_B; //不可访问protected成员
        // son.m_C; //不可访问public成员
    }
    
    // 私有继承
    class Son3 : private Father {
    public:
        void func() {
            // m_A; //不可访问private成员
            m_B;
            m_C;
        }
    };
    
    void test3() {
        Son2 son;
        // son.m_A; //不可访问private成员
        // son.m_B; //不可访问protected成员
        // son.m_C; //不可访问public成员
    }
    
    • 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

    C++有三种权限控制

    • private 只能在本类中的函数中访问,不能被对象访问
    • protected 可以在本类和子类中的函数中访问,不能被对象访问
    • public 可以在本类、派生类中的函数访问,也可在其他函数中被对象访问

    三种继承后:

    • 公共继承:基类的public成员,在子类中为public;基类的protected成员在子类中为protected;基类中的private成员不可访问
    • 保护继承:基类中的public和protected成员在子类中都为protected;基类中的private成员不可访问
    • 私有继承:基类中的public和protected成员在子类中都为private;基类中的private成员不可访问

    4 继承中的构造和析构顺序

    #include 
    
    using namespace std;
    
    class Father {
    public:
        Father() {
            cout << "father constructor" << endl;
        }
        ~Father() {
            cout << "father deconstructor" << endl;
        }
    };
    
    class Son : public Father {
    public:
        Son() {
            cout << "son constructor" << endl;
        }
        ~Son() {
            cout << "son deconstructor" << endl;
        }
    };
    void test() {
        Son son;
    }
    
    int main() {
        test();
        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

    构造顺序:先父类后子类
    析构顺序:先子类后父类
    析构和构造刚好相反

    5 继承同名成员处理

    • 访问子类同名成员,直接访问
    • 访问父类同名成员,需要加作用域
    #include 
    
    using namespace std;
    
    class Father {
    public:
        Father() {
            m_A = 100;
        }
    
        void func() {
            cout << "Father func()" << endl;
        }
    
        void func(int a) {
            cout << "Father func(int a)" << endl;
        }
    
    public:
        int m_A;
    };
    
    class Son : public Father {
    public:
        Son() {
            m_A = 200;
        }
    
        void func() {
            cout << "Son func()" << endl;
        }
    
    public:
        int m_A;
    };
    
    void test() {
        Son son;
        cout << son.m_A << endl;
        cout << son.Father::m_A << endl;
        son.func();
        son.Father::func();
        son.Father::func(10);
    }
    
    int main() {
        test();
        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

    输出:

    200
    100
    Son func()
    Father func()
    Father func(int a)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    子类如果存在和父类同名的成员,则子类会覆盖父类的同名成员。用子类对象调用同名成员,访问的是子类自有的成员,如果要访问父类被覆盖的成员,需要加父类作用域。

    6 继承同名静态成员处理方式

    静态成员不属于对象,属于类,所以静态成员是不被子类继承的

    #include 
    
    using namespace std;
    
    class Father {
    public:
        void func() {
            cout << "Father func()" << endl;
        }
    
        void func(int a) {
            cout << "Father func(int a)" << endl;
        }
    
    public:
        static int m_A;
    };
    
    int Father::m_A = 100;
    
    class Son : public Father {
    public:
        void func() {
            cout << "Father func()" << endl;
        }
    
        void func(int a) {
            cout << "Father func(int a)" << endl;
        }
    
    public:
        static int m_A;
    };
    
    int Son::m_A = 200;
    
    void test() {
        Son son;
        cout << son.m_A << endl;
        cout << son.Father::m_A << endl;
    
        cout << Father::m_A << endl;
        cout << Son::m_A << endl;
    }
    
    int main() {
        test();
        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

    输出:

    200
    100
    100
    200
    
    • 1
    • 2
    • 3
    • 4

    与成员变量的覆盖规则相同,使用作用域访问。
    除了使用对象访问外,也可以通过类名访问。

    7 多继承

    C++允许一个类继承多个类
    多继承可能存在多个父类有同名函数,需要加作用域区分
    实际开发中不建议使用多继承

    #include 
    
    using namespace std;
    
    class Base1 {
    public:
        Base1() {
            m_A = 200;
        }
    
    public:
        int m_A;
    };
    
    class Base2 {
    public:
        Base2() {
            m_A = 100;
        }
    
    public:
        int m_A;
    };
    
    class Son : public Base1, public Base2 {
    
    };
    
    void test() {
        Son son;
        // cout << son.m_A << endl; //编译错误,无法定位访问哪个父类的成员
        cout << son.Base1::m_A << endl;
        cout << son.Base2::m_A << endl;
    }
    
    int main() {
        test();
        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
    200
    100
    
    • 1
    • 2

    同名成员需要添加作用域,否则编译出错,无法定位具体调用哪一个。

    8 菱形继承

    菱形继承就是一个基类,两个派生类继承基类,当前类同时继承两个派生类,形成一个菱形。

    #include 
    
    using namespace std;
    
    class Base {
    public:
        int m_A;
    };
    
    class SubBase1 : public Base {
    };
    
    class SubBase2 : public Base {
    };
    
    class Son : public SubBase1, public SubBase2 {
    };
    
    int main() {
        Son son;
        // son.m_A = 200; //产生歧义
        son.SubBase1::m_A = 100;
        son.SubBase2::m_A = 200;
    
        cout << son.SubBase1::m_A << endl;
        cout << son.SubBase2::m_A << 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

    输出:

    100
    200
    
    • 1
    • 2

    菱形继承主要问题是会有重复数据,导致资源浪费,可以采用虚继承解决菱形继承问题

    9 QA

    private在子类不可访问,那是否继承了呢?

    int main() {
        cout << sizeof(Father) << endl;
        cout << sizeof(Son1) << endl;
        cout << sizeof(Son2) << endl;
        cout << sizeof(Son3) << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    打印类大小

    12
    12
    12
    12
    
    • 1
    • 2
    • 3
    • 4

    说明private也是继承了的,只是无法访问

  • 相关阅读:
    如何在 Vue.js 中引入原子设计?
    【C语言】——内存函数的使用及模拟实现
    ES6箭头函数
    LeetCode 1470. 重新排列数组 / 654. 最大二叉树 / 998. 最大二叉树 II
    py17_Python 编程基础文件操作
    Prometheus安装与配置
    【2022】Python自动化测试,软件测试最全学习路线......
    1 分钟 Serverless 搭建你的首个个人网站(完成就送猫超卡)
    Java项目:ssm流浪狗领养系统
    Win11新建不了文本文档?Win11右键无法新建文本文档的解决方法
  • 原文地址:https://blog.csdn.net/weixin_49274713/article/details/134357412