第六部分思维导图PDF下载C++程序设计 第六章 继承和派生

6.1 继承和派生的基本概念

从一个或多个以前定义的类(基类)产生新类的过程称为派生,这个新类称为派生类。派生的新类同时也可以增加或者重新定义数据和操作,这就产生了类的层次性。

  • 1、增加新的成员
    • 数据成员
    • 成员函数
  • 2、重新定义已有的成员函数

  • 3、改变基类成员的访问权限

C++使用两种基本的面向对象技术

  • 性质约束,即对基类的性质加以限制。
  • 性质扩展,即增加派生类的性质。

C++中有两种继承

  • 单一继承

    • 派生类只能有一个基类
  • 多重继承
    • 派生类可以有多个基类

6.2 单一继承

6.2.1 单一继承的一般形式

  • class 派生类名:访问控制 基类名 {
  • private:
  • 成员声明列表
  • protected:
  • 成员声明列表
  • public:
  • 成员声明列表
  • };

6.2.2 派生类的构造函数和析构函数

  • 构造
    • 应在派生类中声明一个与派生类同名的函数,用于初始化派生类的对象。
    • 在派生类中继承的基类成员的初始化,需要由派生类的构造函数调用基类的构造函数来完成。
    • 类外定义派生类的构造函数
      • 派生类名::派生类名(参数表0):基类名(参数表){…… //函数体};
    • 类内定义派生类的构造函数(内联函数)
      • 派生类名(参数表0):基类名(参数表){…… //函数体};
  • 构造和析构函数是不被继承的,一个派生类只能调用它的直接基类的构造函数。

  • 定义派生类的一个对象时,首先调用直接基类的构造函数,对直接基类进行初始化,然后执行派生类的构造函数,如果该基类仍是一个派生类,则这个过程递归进行。
  • 析构函数的执行顺序和构造函数的顺序相反。

6.2.3 类的保护成员

  • C++规定,使用公有方式产生的派生类的成员函数可以直接访问基类中定义的或从另一个基类继承来的公有成员,但不能访问基类的私有成员。
  • 概念

    • 在类声明中,关键字protected之后声明的是类的保护成员。
    • 对派生类的成员函数而言,基类中protected是公有成员。
    • 对其他函数而言则仍然是私有的,不能被访问。

6.2.4 访问权限和赋值兼容规则

  • 1、共有派生和赋值兼容规则
    • 在公有派生情况下,基类成员的访问权限在派生类中保持不变
      • 1、基类的公有成员在派生类中仍然是公有的。
      • 2、基类的保护成员在派生类中仍然是保护的。
      • 3、基类的不可访问的和私有的成员在派生类中也仍然是不可访问的。
    • 1、派生的对象可以赋值给基类的对象。
      • derived d;
      • base b;
      • b = d;
    • 2、派生类的对象可以初始化基类的引用。
      • derived d;
      • base& br = d;
    • 3、派生类的对象的地址可以赋值给指向基类的指针。
      • derived d;
      • base* pb = &d;
    • 静态成员可以被继承,这时基类对象和派生类对象共享该静态对象。

  • 2、isa 和 has-a 的区别

    • isa
      • 在C++范围内,如果一个基类公有派生出一个派生类,则任何一个要求提供基类对象参数的函数,也能够使用派生类对象作为参数。
    • has-a
      • C++中一个类中包含另一个另的对象,通过让分层的类里包含被分层的类的对象作为其数据成员,以便把一个类建立在另一些类之上。
  • 3、公有继承存取权限表
    • 保护类型成员介于私有和公有之间。
    • 对于派生类
      • 作用与public成员一样
    • 对于派生类的对象、外部函数以及本类系之外的类
      • 作用与private成员一样
  • 4、私有派生
    • 基类的私有和不可访问成员在私有派生类中不可访问
    • 基类公有成员和保护成员变成了派生类的私有成员
    • 私有派生类的对象不能访问继承的基类成员
    • 若再次派生,原基类的公有成员在二次派生的派生类中也将是不可访问
  • 5、保护派生
    • 使原来的权限都降一级使用
      • private-不可访问
      • protected-private
      • public-protected
    • 与私有继承的区别主要在下一级的派生中,即二次派生可以调用第一次派生调用的基类public成员,因为对于第一次派生而言,基类的public为protected,是可以访问的。

6.3 多重继承

概念

  • 一个类从多个基类派生

一般形式

  • class 类名 1:访问控制 类名2,访问控制 类名3,……,访问控制 类名n { ……//定义派生类自己的成员 };

多重继承的规则和单一继承情况一样,多重继承可以视为使单一继承的扩展。

6.4 二义性及其支配规则

6.4.1 作用域分辨符和成员名限定

  • 作用域分辨一般形式

    • 类名::标识符
  • 作用域分辨不仅可以用于类中,而且可以用在函数调用时。
    • 如obj.A::func( );

6.4.2 派生类支配基类的同名函数

  • 派生类D中的名字N支配基类B中同名的名字N,称为名字支配规则。
    • 选择名字时,使用支配者的名字
      • obj.gunc( );
    • 如果要使用被支配者的名字,应使用成员名限定,如
      • obj.B::gunc( );
  • 一个类不能从同一类中直接继承一次以上,如
    • class B: public A, public A{……};
    • 如果必须这样做,可以使用一个中间类。
  • 二义性检查时在访问权限检查之前进行的,因此,成员的访问权限不能解决二义性问题。

  • 如果涉及几层继承关系,对于任一基类中可以存取的成员,都可以通过作用域分辨进行存取。
  • 一般只有派生类中石油的标识符与基类中的标识符同名时,才有必要使用作用域分辨符进行存取。

6.5 典型问题分析

1、派生类没有使用基类的数据成员

2、派生类支配基类的同名函数

  • 对象一定先调用自己的同名成员函数,如果自己没有同名函数,则调用直接基类的同名函数。当然,使用作用域分辨运算符可以指定要调用的函数。

3、二义性

  • 可以使用作用域分辨运算符::和成员名限定解决二义性。

4、友元和派生类

  • 友元声明与访问控制无关。

    • 声明在私有区域和公有区域没有太大区别。
  • 友元关系是无等级的。
    • 友元可以访问任何一个类成员函数可以访问的对象,这比一个派生类可以访问的对象还多。
  • 友元关系不能继承。
    • 一个派生类的友元只能访问该派生类的直接基类的公有和保护成员,不能访问私有成员。
    • 当友元访问直接基类的静态保护成员时,只能使用对象名而不能使用成员名限定。
written by:Vilen
最后修改日期:十一月 5, 2019

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。