C++ Primer Plus Chapter14

Chapter14 C++中的代码重用

包含对象成员的类

valarray类简介

valarray 类由头文件 valarray 支持的一个模板类,用于处理数值。

声明:

valarray<int> q_values;
valarray<double> weights;

初始化:

double gpa[5] = {3.1, 3.5, 3.8, 2.9, 3.3};
valarray<double> v1;		//size = 0 double valarray
valarray<int> v2(8);		//size = 8 int valarray
valarray<int> v3(10,8);		//size = 8 val = 10 int valarray
valarray<double> v4(gpa,4)	//size = 4 val = {3.1, 3.5, 3.8, 2.9}double valarray
valarray<double> v4 = {3.1, 3.5, 3.8, 2.9}		//c++11

组合

例:

class Student{
private:
	string name;
	valarray<double> scores;
}

Student 类只获得了 stringvalarray 类的实现,但没有继承接口。即可以通过成员对象来调用其类的方法,但 Student 对象本身并不能够调用 stringvalarray 类的接口。

关于构造函数初始化

对于使用成员初始化列表语法的构造函数,如果想要初始化成员变量,则应使用成员变量名来调用构造函数:

Student(const char * str, const douvle * pd, int n)
		: name(str), scores(pd,n) {...}

如果想要初始化继承的基类则要使用类名来调用基类的构造函数:

Child(int n) : parent(n) {...};

如果不使用初始化列表语法,则C++将使用成员对象所属类的默认构造函数。

对于初始化列表包含多个项目,这些项目的初始化顺序取决于它们被声明的顺序。

如:

Student(const char * str, const douvle * pd, int n)
		: scores(pd,n), name(str) {...}

name 成员仍将首先初始化。

私有继承

声明

class Student : private std::string, private std::valarray<double>
{
public:
	...
};

私有继承提供继承类的无名称成员。

初始化

Student(const char * str, const double * pd, int n)
	: std::string(str), valarray<double>(pd, n) {...}

不再像组合,使用了类名来调用构造方式,而不是成员名

访问方法

double Student::Average() const
{
	if (valarray<double>::size() > 0)
		return valarray<double>::sum() / valarray<double>::size();
	else
		return 0;
}

私有继承使用类名和作用域解析符来调用方法

访问基类对象

const string & Student::Name() const
{
	return (const string &) *this;
}

私有继承使用强制类型转换可以使得派生类对象强制转换为继承的基类的对象

显示转换为基类对象后也可以调用基类的友元方法了

使用 using 重新定义访问权限

class Student : private std::string, private std::valarray<double>
{
public:
	using std::valarray<double>::min;
	using std::valarray<double>::max;
};

上述声明使得 minmax 方法可用,就像是 Student 类的方法一样,using 声明只适用于继承不适用于包含。

多重继承

虚基类

虚基类使得从多个类派生出的对象只继承一个基类对象。

例:

class Worker{}
class Singer : public Worker {}
class Waiter : public Worker {}
class SingingWaiter : public Singer, public Waiter {}

SingingWaiter 将会包含两个 Waiter 组件,因此这样的语句将会存在二义性

SingingWaiter ed;
Worker * pw = &ed;

通常这种赋值将把基类指针设置为派生对象中的基类对象的地址,但 ed 中包含了两个 Worker 对象。

而使用虚基类将使得 SingingWaiter 只继承一个基类对象:

class Singer : public virtual Worker {}
class Waiter : virtual public Worker {}
class SingingWaiter : public Singer, public Waiter {}

继承的 Singer 对象 和 Waiter 对象共享一个 Worker 对象,可以使用多态了。

虚基类构造函数

C++在基类是虚的时,禁止信息通过中间类自动传递给基类。

如:

class SingingWaiter(const Worker & wk, int p = 0, int v)
					: Waiter(wk,p), Singer(wk,v) {}

上述构造函数的问题在于会通过两条路径来将 wk 传递给 Worker 的构造函数,为了避免这种冲突,所以 wk 并不会传递给 WaiterSinger 。然而编译器必须在构造派生类之前构造基类对象,因此将调用基类的默认构造函数。

如果不想使用基类的默认构造函数,则需要显式调用基类的构造函数:

class SingingWaiter(const Worker & wk, int p = 0, int v)
					: Worker(wk), Waiter(wk,p), Singer(wk,v) {}

类模板

声明

template <class Type>
class A
{
private:
	int top;
	Type items[10];
public:
	A();
	bool isempty();
}

template <class Type>
Stack<Type>::Stack(){
	top = 0;
}

template <class Type>
bool Stack<Type>::isempty(){
	return top == 0;
}

未完

参考书目C++ Primer Plus 第6版