第5章 面向对象编程风格
5.1 面向对象编程概念
面向对象编程的两项最主要的特质是:继承(inherittance)和多态(polymorphism)。
继承能够将一群相关的类组织起来,分享共同的数据和操作。
多态能让我们在这些类之上进行编程时,可以如同操纵单一个体,赋予我们更多弹性来操作类。
继承机制定义了父子关系。父类定义了所有子类共通的公有接口和私有实现。每个子类都可以增加新的或覆盖继承来的东西。
在C++中,父类被称为基类,子类被称为派生类。
面向对象变成风格的第二个独特概念是多态:让基类的pointer或reference得以十分透明地指向其任何一个派生类的对象。
动态绑定(dynamic binding)是面向对象编程风格的第三个独特概念。
如我们写下 mat.check_in(), 函数执行时会根据mat所指的实际对象来决定调用哪一份check_in()。
5.2 漫游:面向对象编程思维
virtual: 默认情况下,Member function的解析在编译时静态地进行,若要在运行时动态进行,我们要在它的声明前加上关键字 virtual,使其成为虚函数。
实现派生类:类名之后跟: public 基类名
如:class Book : public LibMat {
…
}
proteceted 成员,可以被派生类直接访问。
5.3 不带继承的多态
5.4 定义一个抽象基类
定义抽象基类的第一个步骤就是找出所有子类共同的操作行为。
设计抽象基类的下一步,是找出那些操作行为和类型相关。也就是说,那些操作必须根据不同的派生类有不同的实现方式。这些操作行为应该成为整个类继承体系中的虚函数。
第三步,便是找出每个操作的访问层级。(public、protected、private)
每个虚函数,要么有定义,要么将其设置为纯虚函数,
virtual void gen_elems(int pos) = 0;
凡基类有虚函数,应该将其destructor声明为virtual。
5.5 定义一个派生类
派生类必须为从基类继承而来的每个纯虚函数提供对应的实现。
派生类有个Member和基类的Member同名,会遮盖住基类的Member,
5.6 运用继承体系
5.7 基类该多么多么抽象
5.8 初始化、析构、复制
派生类对象的初始化,包括调用基类的constructor然后调用自己的constructor。
5.9 在派生类中定义一个虚函数
如果我们决定覆盖基类的虚函数,那么派生类提供的新定义,其函数原型必须完全符合基类所声明的函数原型。
例外:当基类的返回值是某个基类形式,派生类的同名函数可以返回该基类的派生类。
我们在派生类中,为了覆盖基类的某个虚函数,而进行声明时,不一定要加上关键字virtual。
编译器会根据原型声明决定是否覆盖。
5.10 运行时的类型鉴定机制
typeid 运算符,头文件typeinfo。
让我们得以查询多态化的pointer 或reference,获得其所指对象的实际类型。
static_cast<> 无条件转换
dynamic_cast<> 有条件转换,如果符合则转换,否则返回0