C++ - 继承

继承:

  1. 继承(Inheritance)可以理解为一个类从另一个类获取成员变量和成员函数的过程。例如类 B 继承于类 A,那么 B 就拥有 A 的成员变量和成员函数。
  2. 派生(Derive)和继承是一个概念,只是站的角度不同。继承是子女接收父亲的产业,派生是父亲把产业传承给儿子。
  3. 所以被继承的类称为父类或基类,继承的类称为子类或派生类。“子类”和“父类”通常放在一起称呼,“基类”和“派生类”通常放在一起称呼。
  4. 派生类除了拥有基类的成员,还可以定义自己的新成员,以增强类的功能。以下是两种典型的使用继承的场景:
    1. 当你创建的新类与现有的类相似,只是多出若干成员变量或成员函数时,可以使用继承,这样不但会减少代码量,而且新类会拥有基类的所有功能。
    2. 当你需要创建多个类,它们拥有很多相似的成员变量或成员函数时,也可以使用继承。可以将这些类的共同成员提取出来,定义为基类,然后从基类继承,既可以节省代码,也方便后续修改成员。

继承方式:

1
2
3
class 派生类名:[继承方式] 基类名{
派生类新增加的成员
};
  1. 继承方式限定了基类成员在派生类中的访问权限,包括 public(公有的)、 private(私有的)和 protected(受保护的)。此项是可选项,如果不写, 默认为 private(成员变量和成员函数默认也是 private)。

  2. public 继承方式

    • 基类中所有 public 成员在派生类中为 public 属性;
    • 基类中所有 protected 成员在派生类中为 protected 属性;基类中所有 private 成员在派生类中不能使用。
  3. protected 继承方式

    • 基类中的所有 public 成员在派生类中为 protected 属性;基类中的所有 protected 成员在派生类中为 protected 属性;基类中}的所有 private 成员在派生类中不能使用。
  4. private 继承方式

    • 基类中的所有 public 成员在派生类中均为 private 属性;基类中的所有 protected 成员在派生类中均为 private 属性;基类中的所有 private 成员在派生类中不能使用。
  5. 总结:

    1) 私有成员不能继承

    2) public 继承,成员权限不变

    3) 其他方式继承,成员类型变成此权限

    4) 如果不加继承方式会默认为私有继承

继承1

继承2

继承中构造和析构顺序:

  1. 子类对象在实例化时会首先调用父类的构造函数,父类构造函数执行完毕后,才会调用子类的构造函数

  2. 当父类构造函数有参数时,需要在子类初始化列表(参数列表)中显示调用父类构造函数

  3. 析构函数调用顺序和构造函数相反

    继承3

    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
    #include<iostream>
    using namespace std;
    class Base
    {
    public:
    Base()
    {
    cout<<"Base构造函数!"<<endl;
    }
    ~Base()
    {
    cout<<"Base析构函数!"<<endl;
    }
    };
    class Son:public Base
    {
    public:
    Son()
    {
    cout<<"Son构造函数!"<<endl;
    }
    ~Son()
    {
    cout<<"Son析构函数!"<<endl;
    }
    };
    void test01()
    {
    //创建一个子类对象会同时创建一个父类对象 比如构造函数,自己不写,系统也会默认写上
    //继承中的构造和析构顺序如下:
    //先构造父类,再构造子类,析构的顺序与构造的顺序相反
    Son s1;
    }
    int main()
    {
    test01();
    system("pause");
    return 0;
    }

继承时属性与方法重名 :

  1. 当子类成员和父类成员同名时,子类依然从父类继承同名成员

  2. 如果子类有成员和父类同名,子类访问其成员默认访问子类的成员(本作用域,就近原则)

  3. 在子类通过作用域::进行同名成员区分(在派生类中使用基类的同名成员,显示使用类名限定符)

    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
    #include<iostream>
    using namespace std;
    class Base
    {
    public:
    Base()
    {
    m_A=100;
    }
    void func()
    {
    cout<<"Base - func()调用"<<endl;
    }
    void func(int a)
    {
    cout<<"Son - func()调用"<<endl;
    }
    int m_A;
    };
    class Son:public Base
    {
    public:
    Son()
    {
    m_A=200;
    }
    void func()
    {
    cout<<"Son - func()调用"<<endl;
    }
    int m_A;
    };
    //同名成员属性处理方式
    void test01()
    {
    Son s1;
    cout<<s1.m_A<<endl;//Son 下的 m_A 输出200
    cout<<s1.Base::m_A<<endl;//通过子类对象 访问父类中同名成员,需要加作用域
    }
    //同名成员函数处理方式
    void test02()
    {
    Son s2;
    s2.func();//直接调用 调用的是子类中的同名成员函数
    s2.Base::func();//添加作用域 现在调用的是Base下的func()函数
    //如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数
    //如果想访问到父类中被隐藏的同名成员函数,需要加作用域
    //s.func(100);访问不到 必须加作用域
    s2.Base::func(100);
    }
    int main()
    {
    test01();
    test02();
    system("pause");
    return 0;
    }

多继承:

  1. C++允许一个类继承多个类

  2. 语法:class 子类:继承方式 父类1,继承方式 父类2…..

  3. 多继承可能会引发父类中有同名成员出现,需要加作用域区分

  4. C++实际开发中不建议用多继承

    1
    2
    3
    class D: public A, private B, protected C{
    //类 D 新增加的成员
    }

​ D 是多继承形式的派生类,它以公有的方式继承 A 类,以私有的方式继承 B 类,以保护的方式继承 C 类。 D 根据不同的继承方式获取 A、 B、 C 中的成员,确定它们在派生类中的访问权限。

参考链接: