【本篇文章为博主在学习时做的笔记,本意是怕以后用到的时候恰巧课本不在身边,方便阅读,内容多与很多课本有重合的地方,如有侵权,请告知】
- 组合关系——a part of
- 继承——a kind of
组合对象
- 组合对象的构造函数: 组合类名 (形参表):成员对象1(子形参表1),成员对象2(子形参表2),……
成员对象1(子形参表1),成员对象2(子形参表2),…… —— 初始化列表。
- 类中的成员以其在类中声明的顺序依次构造,初始化列表只是提供调用成员函数对象构造函数的参数。
- 先调用成员对象的构造函数,在调用组合对象的或者函数。
- 访问控制属性:
继承与派生
派生类拥有基类的特性称为继承,由基类产生派生类的过程称为派生。
class 派生类名: 继承方式1 基类名1, 继承方式2 基类名2,...
{
private:
...
protected:
...
public:
...
}
- 继承关系可传递但不允许循环。
- 来自class的继承默认private继承,来自struct 的继承默认public继承。
- 保护成员具有双重角色:对派生类的成员函数而言,它是公有成员,对类外定义的其他函数而言,它是私有成员。
- 各种继承方式:
- 公有继承:
public成员——>public成员 private成员——>无法直接访问 protected成员——>只能通过成员函数访问(相当于protected) - 私有继承:
public成员和protected成员——>private成员。 private成员——>不可直接访问。 基类的成员无法在以后的继承在发挥作用。 (终止了基类的继续派生) - 保护继承:
public成员和protected成员——>protected成员。 private成员——>不可直接访问。 如果类B以保护方式继承自类A,类B再派生出类C,如果是保护或公有方式,则类A的公有和保护成员可被类C间接访问。
派生类名(总参数表):基类名1(参数表1),...,基类名m(参数表m),成员对象名1(成员对象参数表) ..., 成员对象名n(成员 对象参数表n)
{
派生类新增成员的初始化;
}
- 如果基类定义了构造函数,派生类必须也定义构造函数,如果基类没定义构造函数,派生类可以不定义,全部采用默认构造函数。
- 派生类的析构函数只需要负责将新增的非对象成员的清理工作,系统会自己调用基类及成员对象的析构函数进行清理。
- 类型兼容:
派生类:
- 对象可以赋值给基类对象
- 可以初始化基类的引用
- 可将地址赋值给指向基类的指针。
- 单继承的构造函数调用顺序: 先基类的构造函数——内嵌成员对象的构造函数(按他们在类中定义的顺序)——派生类自己的构造函数。
- 多继承的构造函数调用顺序:各基类的构造函数(按声明顺序)——内嵌成员对象的构造函数(按调用顺序)——派生类自己的构造函数。
- 同一基类不允许被直接继承两次。
- 基类的指针数组的各个元素可以指向不同的派生类的对象。
二义性
- 多继承中派生类的多个基类含有同名的成员——>二义性问题
解决办法:
1.成员名限定:通过作用域分辨符::限定采用哪一个基类的。
2.成员重定义(利用同名覆盖)。
- 不同途径继承共同基类产生多个副本。——>间接二义性。
解决办法:虚基类。
虚基类:
——将共同基类设为虚基类,使得共同基类的同名数据成员只有一个副本,同一成员函数只有一个映射。(继承过程中始终维护同一个基类子对象的副本)
定义格式: class 派生类名 : virtual 继承方式 基类名
- 当虚基类定义了带参数的构造函数,虽然所有派生类的构造函数初始化表中都包含对虚基类的初始化,但系统值调用最远派生类中对虚基类的初始化,其他调用被忽略,析构函数也是。
- 在初始化列表中同时出现虚基类和非虚基类构造函数的调用,则虚基类先于非虚基类。
|