15.1 概述
- 抽象,继承与动态绑定都是基础的方法。
- 新标准新增override关键字,用于显示声明改写基类虚函数,一个重要的好处是让编译器帮助我们发现一些覆盖时的失误。
- 动态绑定一般通过指针(引用)实现。
15.2 基类与派生类
虚函数
- 要求:构造函数和静态函数不能是虚函数
- 基类的虚函数在派生类中隐式地也是虚函数。
派生类
- 派生类必须通过基类构造函数初始化基类部分
- 派生类最好遵循基类的接口(即用基类提供的接口操作基类部分)
final关键字
- 阻止继续继承,放在基类定义时的类名后
- 置于函数const限定之后,阻止派生类覆盖(无论是否为虚函数)
15.3 虚函数
虚函数返回的类型通常与基函数匹配,但如果返回类本身指针可以不同,前提是派生类到基类转化可行。
如果用基类指针调用的虚函数有默认实参,则永远使用基函数的默认实参。
通过作用域运算符可以阻止动态绑定。
15.4 抽象基类
纯虚函数可以定义在类的外部(很有意思)。
15.5 访问控制与继承
protected
- 基类的对象不可访问
- 派生类内部可访问
- 派生类的成员只能通过派生类对象访问(与第一条同理)
访问说明符的意义
- 控制派生类对象对基类的访问权限
- 控制派生类的派生类对基类的访问权限
派生类向基类的转换
- 派生类的成员和友元必然可以
- 只有当公有继承时,用户代码可以使用该转换;
- 如果是共有或保护继承,派生类的派生类可以向基类转换
class 与 struct 的第二个区别:默认的访问说明符不同。
15.6 继承中类的作用域
继承类的作用域嵌套在基类中,因此继承类可以直接使用定义在基类的名字(当然也可以覆盖)
无论形参列表是否相同,派生类隐藏基类所有同名函数(解释虚函数的形参列表保持一致的原因)
可以使用using声明,保留部分基类函数
15.7 继承中的构造函数与拷贝控制
基类一般需要一个虚析构函数,同时阻止合成移动构造函数。
派生类的析构函数只负责销毁自己分配的资源。
派生类可使用using操作,生成与基类构造函数一一对应的多个派生类构造函数,其中派生类自己的数据成员被默认初始化。
- 注意点:
- using不改变访问级别
- 基类构造函数有默认实参,派生类不会继承默认实参,而是生成多个版本的构造函数
- 注意点:
15.9 文本查询再探
- 派生类应当与基类保持ISA关系
- 并非所有的构造函数都一定是公有的
- set在类实现中的有用操作
- upper_bound:在multiset中可以跳过与当前关键字相同的所有元素
- set_intersection:合并两个set