C++之类的继承(九)
本文记录了C++中与类的继承相关的容易遗忘的一些知识。
构造与析构
创建派生类的对象时,程序会先调用基类的构造函数,然后再调用派生类的构造函数。
基类的构造函数负责初始化继承的数据成员。派生类的构造函数负责初始化任何新增的数据成员。
派生类的构造函数总会调用基类的构造函数。你可以使用初始化列表语法来指定要使用哪个基类构造函数。否则,将使用默认的基类构造函数。
当派生类的对象销毁时,程序会先调用派生类的析构函数,然后再调用基类的析构函数。
静态绑定与动态绑定
C++规定了虚函数应该如何运行,但将其实现方式留给了编译器编写者。不需要了解实现方法就能使用虚函数,但了解它是如何实现的或许能帮助你更好地理解相关概念,下面是一种实现方式。

使用虚函数在内存和执行速度方面会产生以下适度的开销:
- 每个对象的大小都会增加,增加的量为容纳一个地址所需的空间。
- 编译器会为每个类创建一个(数组形式的)虚函数地址表。
- 对于每次函数调用,都会多一个步骤:去表中查找地址。
要记住,尽管非虚函数比虚函数效率略高,但它们不提供动态绑定。
抽象基类
C++有一种通过使用纯虚函数来提供未实现函数的方法。纯虚函数在其声明的末尾带有
= 0,正如Area()方法所示:
1 | class BaseEllipse // abstract base class |
当一个类声明包含纯虚函数时,就不能创建该类的对象。其理念是,包含纯虚函数的类仅作为基类存在。
简而言之,原型中的
=0表明该类是一个抽象基类,并且该类不一定非要定义这个函数(也可以定义)。= 0
的作用是告诉编译器
“这个函数是纯虚的,该类是抽象类”,它只是一个标识,而非 “禁止定义”
的指令。编译器允许你为纯虚函数编写函数体,只是函数体不能写在类的内部,必须写在类外部。
ABC哲学
ABC方法是一种系统性和条理性更强的处理继承的方式。在设计ABC之前,首先必须构建一个模型,明确需要哪些类来表示一个编程问题,以及这些类之间是如何相互关联的。一种观点认为,如果设计了一个类的继承层次结构,那么唯一的具体类应该是那些永远不会作为基类的类。这种方法往往能产生更简洁的设计,减少复杂性。
一种理解ABC的方式是将其视为对接口的一种强制实施。ABC要求其纯虚函数必须在任何具体的派生类中被重写,这就迫使派生类遵守ABC所设定的接口规则。这种模式在基于组件的编程范式中很常见,在这种范式下,ABC的使用使组件设计者能够创建一份“接口契约”,所有从该ABC派生的组件都能保证至少支持ABC所规定的通用功能。