星球狂想战队|一起来学C++:C++中的代码重用( 二 )


这是您需要学习的唯一新语法 , 它非常简单 。
类特性意味着要使用valarray对象 , 需要了解这个类的构造函数和其他类方法 。 下面是几个使用其构造函数的例子:
doublegpa[5]={3.1,3.5,3.8,2.9,3.3};valarrayv1;//anarrayofdouble,size0valarrayv2(8);//anarrayof8intelementsvalarrayv3(10,8);//anarrayof8intelements,//eachsetto10valarrayv4(gpa,4);//anarrayof4elements//initializedtothefirst4elementsofgpa从中可知 , 可以创建长度为零的空数组、指定长度的空数组、所有元素度被初始化为指定值的数组、用常规数组中的值进行初始化的数组 。 在C++11中 , 也可使用初始化列表:
valarrayv5={20,32,17,9};//C++11下面是这个类的一些方法 。
operator:让您能够访问各个元素 。 size():返回包含的元素数 。 sum():返回所有元素的总和 。 max():返回最大的元素 。 min():返回最小的元素 。还有很多其他的方法 , 其中的一些将在第16章介绍;但就这个例子而言 , 上述方法足够了 。
14.1.2Student类的设计至此 , 已经确定了Student类的设计计划:使用一个string对象来表示姓名 , 使用一个valarray来表示考试分数 。 那么如何设计呢?您可能想以公有的方式从这两个类派生出Student类 , 这将是多重公有继承 , C++允许这样做 , 但在这里并不合适 , 因为学生与这些类之间的关系不是is-a模型 。 学生不是姓名 , 也不是一组考试成绩 。 这里的关系是has-a , 学生有姓名 , 也有一组考试分数 。 通常 , 用于建立has-a关系的C++技术是组合(包含) , 即创建一个包含其他类对象的类 。 例如 , 可以将Student类声明为如下所示:
classStudent{private:stringname;//useastringobjectfornamevalarrayscores;//useavalarrayobjectforscores...};同样 , 上述类将数据成员声明为私有的 。 这意味着Student类的成员函数可以使用string和valarray类的公有接口来访问和修改name和scores对象 , 但在类的外面不能这样做 , 而只能通过Student类的公有接口访问name和score(请参见图14.1) 。 对于这种情况 , 通常被描述为Student类获得了其成员对象的实现 , 但没有继承接口 。 例如 , Student对象使用string的实现 , 而不是char*name或charname[26]实现来保存姓名 。 但Student对象并不是天生就有使用函数stringoperator+=()的能力 。
接口和实现
使用公有继承时 , 类可以继承接口 , 可能还有实现(基类的纯虚函数提供接口 , 但不提供实现) 。 获得接口是is-a关系的组成部分 。 而使用组合 , 类可以获得实现 , 但不能获得接口 。 不继承接口是has-a关系的组成部分 。
对于has-a关系来说 , 类对象不能自动获得被包含对象的接口是一件好事 。 例如 , string类将+运算符重载为将两个字符串连接起来;但从概念上说 , 将两个Student对象串接起来是没有意义的 。 这也是这里不使用公有继承的原因之一 。 另一方面 , 被包含的类的接口部分对新类来说可能是有意义的 。 例如 , 可能希望使用string接口中的operator
14.1.3Student类示例现在需要提供Student类的定义 , 当然它应包含构造函数以及一些用作Student类接口的方法 。 程序清单14.1是Student类的定义 , 其中所有构造函数都被定义为内联的;它还提供了一些用于输入和输出的友元函数 。
程序清单14.1studentc.h
//studentc.h--definingaStudentclassusingcontainment#ifndefSTUDENTC_H_#defineSTUDENTC_H_#include#include#includeclassStudent{private:typedefstd::valarrayArrayDb;std::stringname;//containedobjectArrayDbscores;//containedobject//privatemethodforscoresoutputstd::ostream&arr_out(std::ostream&os)const;public:Student():name("NullStudent"),scores(){}explicitStudent(conststd::string&s):name(s),scores(){}explicitStudent(intn):name("Nully"),scores(n){}Student(conststd::string&s,intn):name(s),scores(n){}Student(conststd::string&s,constArrayDb&a):name(s),scores(a){}Student(constchar*str,constdouble*pd,intn):name(str),scores(pd,n){}~Student(){}doubleAverage()const;conststd::string&Name()const;double&operator[](inti);doubleoperator[](inti)const;//friends//inputfriendstd::istream&operator>>(std::istream&is,Student&stu);//1wordfriendstd::istream&getline(std::istream&is,Student&stu);//1line//outputfriendstd::ostream&operator<为简化表示 , Student类的定义中包含下述typedef:


推荐阅读