c++促进代码重用的方式:
其中公有继承用于实现is-a关系,
而包含、私有继承和公有继承用于实现has-a关系(即新的类包含另一个类的对象)。
该类模板由头文件"valarray"支持.
模板特性意味着声明对象时,必须指定具体的数据类型
学习使用类模板valarray,必须了解这个类的构造函数及其他类方法。
valarray的使用方法举例:
double gpa[5] = {3.1, 3.5, 2.9, 8.7, 4.6};
valarray<double> v1; // double型数组,size = 0
valarray<int> v2(8); // int型数组,size = 8
valarray<int> v3(10,8); // 8个int数组,每个元素设置值为10
valarray<int> v4(gpa,4); //size = 4, val = gpa ,type = int
一些方法:
operator[]() : 用[]访问各个元素
size() : 返回包含的元素数
sum()
max()
min()
class Student
{
private:
// 将该typedef放在类定义的私有部分意味着可以在Student类的实现中使用它
// 但在student类外面不能使用
typedef std::valarray<double> ArrayDb;
std::string name; // contained object
ArrayDb scores; // contained object
......
}
学生不是姓名,也不是分数,而是学生有姓名和分数,所以这里是has-a关系,所以这里使用组合的方式来建立has-a关系。
上述将数据成员设定为私有的,这意味Student类的成员函数可以使用string类和 valarray类的公有接口来访问和修改name对象和score对象,
但是在类外访问不到成员类对象的接口和数据,只能通过Student类提供的接口对私有的成员类进行访问。
也就是说:
类对象不能自动获得被包含的成员对象的接口,但是可以在类方法的实现中使用成员对象的接口来修改成员对象。
以下所有的构造函数都是内联的,还提供了一些用于输入输出的友元函数。
class Student
{
private:
typedef std::valarray<double> ArrayDb;
std::string name;
ArrayDb scores;
// private method for scores output
std::ostream & arr_out(std::ostream & os) const;
public:
// dafault construction
Student() : name("Null Student"), scores() {}
explicit Student(const std::string & s)
: name(s), scores() {}
// 这里的参数int n是指数组元素的个数,不是数组中的值
// 而一个参数的构造函数有可能会被用于隐式类型转换,发生不必要的错误。 // 使用关键字explicit关闭隐式转换,避免发生未经允许的隐式类型转换
explicit Student(int n) : name("Nully"), scores(n) {}
Student(const std::string & s, int n)
: name(s), scores(n) {}
Student(const std::string & s, const ArrayDb & a)
: name(s), scores(a) {}
Student(const char * str, const double * pd, int n)
: name(str), scores(pd, n) {}
~Student() {}
double Average() const;
const std::string & Name() const;
double & operator[](int i);
double operator[](int i) const;
// friends
// input
friend std::istream & operator>>(std::istream & is,
Student & stu); // 1 word
friend std::istream & getline(std::istream & is,
Student & stu); // 1 line
// output
friend std::ostream & operator<<(std::ostream & os,
const Student & stu);
};
需要注意的点:
C++要求在构建对象的其他部分之前,先构建继承对象的所有成员的所有成员对象;因此如果省略初始化列表,C++将使用成员对象所属类的默认构造函数。
例1:
//public methods
// 被包含的对象的接口不是公有的,但是可以在类方法中使用他们,但是不在类外使用
// 该方法内部使用了valarray的方法size和sum
double Student::Average() const
{
if (scores.size() > 0)
return scores.sum()/scores.size();
else
return 0;
}
例2
这里的stu.name是一个string对象,os << string ,将调用string类的 <<运算符重载函数,进行输出。
// use string version of operator<<()
ostream & operator<<(ostream & os, const Student & stu)
{
// 这里使用stu.name将调用operator<<(ostream &)
os << "Scores for " << stu.name << ":\n";
stu.arr_out(os); // use private method for scores
return os;
}