类的多继承

类型兼容规则

一、一个公有派生类的对象在使用上可以被当作基类的对象,反之则禁止。具体表现在:

  1. 派生类的对象可以隐含转换为基类对象。
  2. 派生类的对象可以初始化基类的引用。
  3. 派生类的指针可以隐含转换为基类的指针。
  • 通过基类对象名、指针只能使用从基类继承的成员
  • 类型兼容,多态的另一重要特色。

基类与派生类的对应关系

  1. 单继承:派生类只从一个基类派生。
  2. 多继承:派生类从多个基类派生
  3. 多重派生:由一个基类派生出多个不同的派生类。
  4. 多层派生:派生类又作为基类,继续派生新的类。

一、派生类的构造、析构函数

  1. 由于基类的构造函数和析构函数不能被继承,在派生类中,如果对派生类新增的成员进行初始化,就必须为派生类添加新的构造函数。
  2. 但是,派生类的构造函数只负责对派生类新增成员的初始化,对所有从基类继承下来的成员,其初始化工作仍由基类的构造函数完成。
  3. 对派生对象的扫尾、清理工作也需要加入新的析构函数。
  4. 派生类的构造函数需要给基类的构造函数传递参数。
  • 派生类构造函数声明的选择性
  1. 如果对基类初始化,需要调用基类的带有形参表的构造函数时,派生类就必须声明构造函数,提供一个将形参传递给基类构造函数的途径,保证在基类初始化时能够获得必要的数据。派生类构造函数应在初始化列表基类构造函数提供参数
  2. 如果不需要调用基类的带参数的构造函数,也不需要调用新增的成员对象的带参数的构造函数,派生类也可以不声明构造函数,而是采用默认构造函数

  • 构造函数的执行顺序
  1. 调用基类构造函数,调用顺序按照它们被继承时声明的顺序(从左向右)。
  2. 成员对象进行初始化,初始化顺序按照它们在类中声明的顺序
  3. 执行派生类的构造函数体中的内容。

  • 复制/拷贝构造函数
  1. 建立派生类对象时,若没有编写拷贝构造函数,编译器会生成一个隐含的拷贝构造函数。该函数先调用基类的拷贝构造函数,再为派生类新增的成员对象执行拷贝。
  2. 若编写派生类的拷贝构造函数,则需要为基类相应的拷贝构造函数传递参数。
  • 继承时的析构函数
  1. 析构函数也不被继承,派生类可自行声明。
  2. 析构函数无返回类型、无参数、相对简单。声明方法与无继承关系时类的析构函数相同。
  3. 不需要显式地调用基类的析构函数,系统会自动隐式调用。

  • 析构函数的执行顺序
  1. 执行派生类析构函数体中的内容
  2. 调用派生类新增成员对象的析构函数;析构顺序与它们在类中的声明的顺序相反。
  3. 调用基类析构函数:对这些析构函数的调用顺序,恰与构造函数的调用顺序相反。
  • 同名隐藏规则
  1. 对于在不同作用域声明的标识符,可见性原则是:如果存在两个或多个具有包含关系的作用域,外层声明了一个标识符,而内层没有再次声明同名标识符,那么外层标识符在内层仍然可见。
  2. 如果在内层声明了同名标识符,则外层标识符在内层不可见,这时,内层标识符隐藏了外层同名标识符,这种现象称为同名隐藏规则。

派生类中的同名隐藏:

  1. 如果派生类中声明了与基类成员函数同名的新函数,即使函数的参数表不同,从基类继承的同名函数的所有重载形式也都会被隐藏。
  2. 如果某派生类的多个基类拥有同名的成员:
  1. 若派生类又新增这样的同名成员,则派生类成员将隐藏所有基类的同名成员。
  2. 若不新增同名成员,则通过“对象名.成员名”或“对象指针->成员名” 唯一标识成员。
  • 派生类中同名成员的访问
  1. 当派生类与基类中有相同成员时:
  1. 若未强行指名,则通过派生类对象使用的是派生类中的同名成员。

  对象名.成员名 或对象指针->成员名

  1. 如要通过派生类对象访问基类中被隐藏的同名成员,应使用基类名限定。

对象名.类名::成员名(“::”作用域分辨符)

对象指针->类名::成员名

  • 多继承中的二义性问题
  1. 在多继承时,基类与派生类之间,或基类之间出现同名成员时,将出现访问时的二义性(不确定性),可采用虚函数或同名隐藏规则来解决。
  2. 当派生类从多个基类派生,而这些基类又从同一个基类派生,则在访问此共同基类中的成员时,将产生二义性——采用虚基类来解决。
  • 虚基类

虚基类的引入:用于有共同基类的场合

声明形式:以virtual修饰说明基类,例如:class B1:virtual public B

作用:主要用来解决多继承时,可能发生的对同一基类继承多次而产生的二义性问题。

为最远的派生类提供唯一的基类成员,不重复产生多次拷贝

注意:在第一级继承时就要将共同基类设计为虚基类。

  • 虚基类及其派生类构造函数
  1. 建立对象时所指定的类成为最(远)派生类。
  2. 虚基类的成员是由最派生类的构造函数通过调用虚基类的构造函数进行初始化的
  3. 在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中给出对虚基类的构造函数的调用。如果未列出,则表示调用该虚基类的默认构造函数。
  4. 在建立对象时,只有最派生类的构造函数调用虚基类的构造函数,该派生类的其他基类对虚基类构造函数的调用被忽略。
  • 虚基类的初始化

虚基类初始化时,构造函数的调用顺序规则:

  1. 同一层派生中包含多个虚基类时,虚基类的构造函数按它们派生时声明的先后次序调用。
  2. 如某虚基类是由实基类派生而来,则先调用此实基类的的构造函数,再调用虚基类的构造函数,最后才是派生类的构造函数。
  3. 若同一层派生中,同时存在虚基类与实基类,应先调用虚基类的构造函数,再调用实基类的构造函数,最后调用派生类的构造函数。
  • 组合与继承

概念:通过已有类来构造新类的两种基本方式

  1. 组合:B类中存在一个A类型的内嵌对象

-有一个(has-a)关系:表明每个B类型对象“有一个”A类型对象

-A类型对象与B类型对象是部分与整体关系

-B类型的接口不会直接作为A类型的接口

  1. 公有继承:A类是B类的公有基类

-是一个(is-a)关系:表明每个B类型对象“是一个”A类型对象

-A类型对象与B类型对象是一般与特殊关系

(回顾类的兼容性原则:在需要基类对象的任何地方,都可以使用公有派生类的对象来替代)

-B类型对象包括A类型的全部接口

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Momo_159357

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值