• C++中的继承


    继承

    类之间的继承

    可以扩展 C + + 中的类,即创建保留基类特征的新类。这个过程称为继承,涉及一个基类和一个派生类: 派生类继承基类的成员,在这些成员之上派生类可以添加自己的成员。

    例如,让我们想象一系列的类来描述两种多边形: 矩形(rectangles)和三角形(triangles)。这两个多边形有一些共同的属性,例如计算它们的面积所需的值: 它们都可以简单地用高度和宽度(或基数)来描述。

    这可以在类的世界中用一个Polygon类来表示,我们可以从这个类派生出另外两个多边形: 矩形Rectangle)和三角形(Triangle):


    Polygon 类将包含多边形所具有的一些通用的成员。如在我们的例子中: 宽度和高度。矩形和三角形将是它的派生类,具有各自特定特征。

    从其他类派生的类继承基类的所有可访问成员。这意味着如果一个基类包含一个成员 A,并且我们从它派生一个包含另一个成员 B 的类,那么派生的类将同时包含成员 A 和成员 B。

    两个类的继承关系在派生类中声明:

    class derived_class_name: public base_class_name { /*...*/ };

    • 其中derived_class_name 是派生类的名称,base _ class _ name 是它所继承的基类的名称。公共访问说明符也可以由其他访问说明符(protected 或 private)。
    1. // 派生类
    2. #include
    3. using namespace std;
    4. class Polygon {
    5. protected:
    6. int width, height;
    7. public:
    8. void set_values (int a, int b)
    9. { width=a; height=b;}
    10. };
    11. class Rectangle: public Polygon {
    12. public:
    13. int area ()
    14. { return width * height; }
    15. };
    16. class Triangle: public Polygon {
    17. public:
    18. int area ()
    19. { return width * height / 2; }
    20. };
    21. int main () {
    22. Rectangle rect;
    23. Triangle trgl;
    24. rect.set_values (4,5);
    25. trgl.set_values (4,5);
    26. cout << rect.area() << '\n';
    27. cout << trgl.area() << '\n';
    28. return 0;
    29. }

    • 矩形和三角形类的对象都包含从Polygon类继承的成员,这些对象是: width、 height 和 set _ value。
    • 类 Polygon 中使用的private访问说明符类似于 private。其唯一的区别实际上与继承有关: 当一个类继承另一个类时,派生类的成员可以访问从基类继承的private成员,但不能访问其私有(private)成员。
    • 通过将 width 和 height 声明为 protected 而不是 private,这些成员也可以从派生类 Recangle 和 Triangle 访问,而不仅仅是从 Polygon 的成员访问。如果它们是公共的,那么可以从任何地方访问它们。


    我们可以总结出不同的访问类型,根据这些类型,函数可以通过以下方式访问它们:

    访问publicprotectedprivate
    类内成员yesyesyes
    派生类成员yesyesno
    非成员yesnono

    • 其中“非成员”表示来自类外部的任何访问,例如来自 main、来自另一个类或函数的访问。


    在上面的示例中,由矩形和三角形继承的成员拥有与其基类 Polygon 相同的访问权限:

    1. Polygon::width // protected access
    2. Rectangle::width // protected access
    3. Polygon::set_values() // public access
    4. Rectangle::set_values() // public access  
    • 这是因为在每个派生类上使用 public 关键字声明了继承关系:class Rectangle: public Polygon { /* ... */ }

    • 由于 public 是最可访问的级别,因此通过指定此关键字,派生类Recangle将继承与基类中具有相同级别的所有成员。


    使用 protected 时,基类的所有公共(public)成员在派生类中继承为 protected。相反,如果指定了最受限制的访问级别(private) ,则所有基类成员都将作为 private 继承。

    例如,如果daughter是从mother派生的类,我们定义为:

    class Daughter: protected Mother;

    • 如果没有为继承指定访问级别,则编译器为类的假定关键字为 private,而struct 的继承默认为 public。
    • 实际上,C + + 中的大多数继承用例都应该使用public继承。

    从基类继承什么?

    原则上,公共派生类继承基类的每个成员,除了:

    • 它的构造函数和析构函数
    • 其赋值运算符成员(运算符 =)
    • 它的友元
    • 它的私有成员


    即使对基类的构造函数和析构函数的访问不是继承的,它们也会被派生类的构造函数和析构函数自动调用。

    除非另有说明,否则派生类的构造函数将调用其基类的默认构造函数(即不带参数的构造函数)。使用初始化列表中用于初始化成员变量的相同语法,可以调用基类的另一个构造函数:

    • 初始化列表:就是在参数列表()与构造函数主体{}之间初始化的一种语法格式,使用冒号:,多个初始化用逗号隔开。


    derived_constructor_name (parameters) : base_constructor_name (parameters) {...}

    例如:

    1. // 构造函数与派生类 || constructors and derived classes
    2. #include
    3. using namespace std;
    4. class Mother {
    5. public:
    6. Mother ()
    7. { cout << "Mother: no parameters\n"; }
    8. Mother (int a)
    9. { cout << "Mother: int parameter\n"; }
    10. };
    11. class Daughter : public Mother {
    12. public:
    13. Daughter (int a)
    14. { cout << "Daughter: int parameter\n\n"; }
    15. };
    16. class Son : public Mother {
    17. public:
    18. Son (int a) : Mother (a)
    19. { cout << "Son: int parameter\n\n"; }
    20. };
    21. int main () {
    22. Daughter kelly(0);
    23. Son bud(0);
    24. return 0;
    25. }

    输出结果:

    Mother: no parameters
    Daughter: int parameter
    
    Mother: int parameter
    Son: int parameter


    请注意在创建新的 Daughter 对象时调用 Mother 的构造函数与在创建 Son 对象时调用 Mother 的构造函数之间的区别。区别在于 Daughter 与 Son 的构造函数声明不同:

    Daughter (int a)         // 没有特别说明: 调用默认构造函数

    Son (int a) : Mother (a) // 调用这个特定的构造函数(有参构造)

    多重继承

    一个类可以通过简单地指定更多的基类(用逗号分隔)来继承不止一个类。例如,再继承在屏幕上打印 Output 的特定类,我们可以写:

    class Rectangle: public Polygon, public Output;

    class Triangle: public Polygon, public Output; 


    完整的示例:

    1. // 多重继承 || multiple inheritance
    2. #include
    3. using namespace std;
    4. class Polygon {
    5. protected:
    6. int width, height;
    7. public:
    8. Polygon (int a, int b) : width(a), height(b) {}
    9. };
    10. class Output {
    11. public:
    12. static void print (int i);
    13. };
    14. void Output::print (int i) {
    15. cout << i << '\n';
    16. }
    17. class Rectangle: public Polygon, public Output {
    18. public:
    19. Rectangle (int a, int b) : Polygon(a,b) {}
    20. int area ()
    21. { return width*height; }
    22. };
    23. class Triangle: public Polygon, public Output {
    24. public:
    25. Triangle (int a, int b) : Polygon(a,b) {}
    26. int area ()
    27. { return width*height/2; }
    28. };
    29. int main () {
    30. Rectangle rect (4,5);
    31. Triangle trgl (4,5);
    32. rect.print (rect.area());
    33. Triangle::print (trgl.area());
    34. return 0;
    35. }

    输出结果: 

    20
    10  
    

    参考网址:https://cplusplus.com/doc/tutorial/inheritance/ 

  • 相关阅读:
    聊聊对Andorid的FileProvider的理解
    springboot中如何进行业务层测试事务回滚
    05- 基于UDS协议的故障代码状态字节及检测机制
    南卡对比评测明基护眼灯,2022双十一哪一款护眼台灯更值得入手
    SpringBoot2.0数据访问之整合数据源(Druid)
    IDEA web工程入门笔记
    vue3后台管理框架之svg封装为全局组件
    学周刊杂志学周刊杂志社学周刊编辑部2022年第24期目录
    第六章 图(中)【图的基本操作和遍历】
    上周热点回顾(12.18-12.24)
  • 原文地址:https://blog.csdn.net/weixin_58045467/article/details/127709182