C++ 中的代码重用
C++中的代码重用
C++的一个主要目的是促进代码的重用,公有继承是实现这种目标的机制之一。本章介绍其他的方法,其中之一是使用类成员的方法,这种方法称为包含、组合或层次化,另外一种方法是使用保护继承或私有继承
接口和实现
使用公有继承时,类可以继承接口,可能还有实现(基类的纯虚函数提供接口,但不提供实现)。获得接口的是 is-a 关系的组成部分。而使用组合,类可以获得实现,但不获得接口。不继承接口是 has-a 关系
举个例子
公有继承继承接口,也就是说
私有继承只继承实现,不继承接口
不继承接口,但继承实现。内部可以使用基类方法,但是外部无法使用。打个比方,汽车和发动机的关系,汽车并不是发动机,但是汽车需要使用发动机。这就是 has-a 关系
关键字 explicit
只用一个参数作为入参的构造函数将作为从参数类型到类类型的隐式转换函数,这通常不是我们期望看到的,使用explicit
可以关闭隐式转换。
若没加 explicit 表示允许一个unsigned int
转换为Base
类型,如果这不是我们所期望的,请使用explicit
修饰
C++包含能让程序员限制程序结构的特性---使用explicit
防止单个参数构造函数的隐式转换,使用const
限制方法修改数据等等,这样做的根本原因是:在编译阶段出现错误优于在运行阶段出现的错误
私有继承
初始化基类组件
私有继承没有采用包含的方式,必须使用公有继承的技术,采用初始化列表的方式进行初始化
访问基类的方法
使用私有继承时,只能在派生类中使用基类的方法,私有继承能够使用类名和作用域解析运算符来调用基类的方法,如之前的代码
访问基类对象
如果期望在派生类中直接访问基类对象,使用强制类型转换可以达成。
访问基类的友元函数
答案还是强制类型转换,原因是友元函数使用静态联编。
包含 or 私有继承?
包含也可以用来建立 has-a 关系,如果新类需要访问原有类的保护成员,或需要重新定义虚函数,则必须使用私有继承。
保护继承
使用保护继承时,基类的公有成员和保护成员都将成为派生类的保护成员。基类的接口在派生类中也是可用的,但在继承层次结构之外是不可用的。当派生类再派生出另外一个类,私有继承和保护继承之间的区别便呈现出来了。
类模板
可以用模板参数来实现代码的重用
关键字class
(此处与typename
完全等价)指出 T 为类型参数
模板的具体化分为以下几种情况
隐式实例化
即声明一个或多个对象,指出所需的类型,而编译器使用通用模板提供的处方生成具体的类定义:
编译器在需要对象之前,不会生成类的隐式实例化
显示实例化
使用关键字telplate
并指出所需类型来声明类时,会生成类的显示实例化。
显示具体化
显示具体化(explicit specialization
)是特定类型的定义。有时候,可能需要在为特殊类型实例化,不使用通用的模板,对模板进行修改。
具体化类模板定义的格式如下
举一个例子
当vecto
r 实例化为bool
对象时,直接使用一个byte
保存一个元素即可,节约内存。
部分具体化
C++还允许部分具体化(partial specialization
),即部分限制模板的通用性。举一个常用的例子,含有指针的类和不含指针的类有很大的区别。就可以为指针提供特殊版本来部分具现化现有的模板:
评论