C++中的代码重用
本章内容包括:
Has-a关系
包含对象成员的类
模板类valarray
私有和保护继承
多重继承
虚基类
创建类模板
使用类模板
模板的具体化
C++ 的一个主要目标是促进代码重用,公有继承是实现这种目标的机制之一,但并不是唯一的机制,本章介绍其他方法:
1. 使用类成员:本身是另一个类的对象,这种方法称为包含、组合或层次化;
2. 使用私有或保护继承:私有继承和保护继承用于实现 has-a 关系,即新的继承包含另一个类的对象;
3. 多重继承使用两个或者更多的基类派生出新的类,将基类的功能组合在一起
类模板是另一种重用代码的方法,类模板使我们能够使用通用术语定义类,然后使用模板来创建针对特定类型定义的特殊类:
例如,可以定义一个通用的栈模板,然后使用该模板创建一个用于表示int值的栈的类和一个用于表示double 值的类
14.1 包含对象的类
14.1.1 valarray 类简介
valarray 类由头文件valarray支持,用于处理数值(或具有类似特性的类);
valarray 类支持将数组中所有元素的值相加以及在数组中找到最大和最小的值等操作;
valarray 被定义为一个模板类,以便能够处理不同的数据类型:
valarray<int> q_values; // an array of int
valarray<double> weights; // an array of double
valarray 类的构造函数:
double gpa[5] = {3.1, 3.5, 3.8, 2.9, 3.3};
valarray<double> v1; // 创建长度为0的数组
valarray<int> v2(8); // 创建长度为8的数组,初始化为0
valarray<int> v3(10, 8); // 创建长度为8的数组,初始化为特定值10
valarray<double> v4(gpa, 4); // 用数组中的值进行初始化数组
C++11,也使用初始化列表: valarray<int> v5 = { 20, 32, 17, 9 };
valarray 类的一些方法:
operator [] () :访问各个元素
size() :返回包含的元素数
sum(): 返回所有元素的总和
max(): 返回最大的元素
min() : 返回最小的元素
14.1.2 Student 类的设计
通常,用于建立has-a关系的C++技术是组合(包含),即创建一个包含其他类对象的类:
class Student
{
private:
string name; // use a string object for name
valarray<double> scores; // use a valarray<double> object for scores
. . .
} ;
使用公有继承时,类可以继承接口,可能还有实现(基类的纯虚函数提供接口,但不提供实现)。获得接口是 is-a 关系的组成部分;
而使用组合,类可以获得实现,但不能获得接口。不继承接口是has-a关系的组成部分;
C++包含让程序员能够限制程序结构的特性: 在编译阶段出现错误优于在运行阶段出现错误
使用 explicit 防止但参数构造函数的隐式转换;
使用 const 限制方法的修改;
被包含对象的接口不是公有的,但是可以在类方法中使用它:
scores是一个 valarray 对象,所以它可以调用 valarray 类的成员函数
14.2 私有继承
C++ 还有另一种实现 has-a 关系的途径——私有继承:
使用私有继承,基类的公有成员和保护成员都将成为派生类的私有成员;
基类方法将不会成为派生对象公有接口的一部分,但可以在派生类的成员函数中使用它们
使用私有继承,派生类不继承基类的接口,正如被包含对象中看到的,这种不完全继承是 has-a 关系的一部分;