C++学习之路(十六)

第14章   C++中的代码重用

1.包含对象成员的类

(1)valarray类简介

valarray被定义为一个模板类,以便能够处理不同的数据类型。使用valarray类来声明一个对象时,需要在标识符valarray后面加上一对尖括号,并在其中包含所需的数据类型:

valarray<int> q_values;       //an array of int
valarray<double> weights;     //an array of double

下面是几个使用其构造函数的例子:

double gpa[5]={3.1,3.5,3.8,2.9,3.3};
valarray<double> v1;          //an array of double, size 0
valarray<int> v2(8);          //an array of 8 int elements
valarray<int> v3(10,8);       //an array of 8 int elements, each set to 10
valarray<double> v4(gpa,4);   //an array of 4 elements, initialized to the first 4 elements of gpa

从中可知,可以创建长度为零的空数组、指定长度的空数组、所有元素度被初始化为指定值的数组、用常规数组中的值进行初始化的数组。在C++11中,也可以使用初始化列表:

valarray<int> v5={20,32,17,9};       //C++11

下面是这个类的一些方法:

1)operator[ ]( ):让您能够访问各个元素

2)size():返回包含的元素数

3)sum():返回所有元素的总和

4)max():返回最大的元素

5)min():返回最小的元素

(2)初始化被包含的对象

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

因为该构造函数初始化的是成员对象,而不是继承的对象,所以在初始化列表中使用的是成员名,而不是类名;C++要求在构建对象的其他部分之前,先构建继承对象的所有成员对象,如果省略初始化列表,C++将使用成员对象所属类的默认构造函数

(3)使用被包含对象的接口

被包含对象的接口不是公有的,但可以在类方法中使用它。例如,下面的代码说明了如何定义一个返回学生平均分数的函数:

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

可以定义一个使用string版本的<<运算符的友元函数:

//use string version of operator<<()
ostream & operator<<(ostream & os, const Student & stu)
{
       os<<"Scores for"<<stu.name<<":\n";
       ...
}

同样,该函数也可以使用valarray的<<实现来进行输出,不幸的是没有这样的实现;因此,Student类定义了一个私有辅助方法来处理这种任务:

//private method
ostream & Student::arr_out(ostream & os) const
{
   int i;
   int lim=scores.size();
   if(lim>0)
   {
      for(i=0;i<lim;i++)
      {
         os<<scores[i]<<" "";
         if(i%5==4)
         os<<endl;
      }
      if(i%5!=0)
         os<<endl;
   }
   else
      os<<" empty array";
   return os;
}
//use string version of operator<<()
ostream & operator<<(ostream & os, const Student & stu)
{
   os<<"Scores for "<<stu.name<<":\n";
   stu.arr_out(os);     //use private method for scores
   return os;
}

辅助函数也可以用作其他用户级输出函数的构建块—如果提供符合条件的函数

2.私有继承

1)包含与私有继承的区别:

包含将对象作为一个命名的成员对象添加到类中,而私有继承将对象作为一个未被命名的继承对象添加到类中(包含版本提供了两个被显式命名的对象成员,而私有继承提供了两个无名称的子对象成员);子对象来表示通过继承或包含添加的对象;对于继承类,使用类名而不是成员名来标识构造函数

包含与私有继承的相同点:获得实现,但不获得接口

2)初始化基类组件

对于构造函数,包含将使用这样的构造函数:

Student(const char * str, const double *pd, int n)
      :name(str), scores(pd,n) {}        //use object names for containment

对于继承类,新版本的构造函数将使用成员初始化列表语法,它使用类名而不是成员名来标识构造函数:

Student(const char * str, const double * pd, int n)
     :std::string(str),ArrayDb(pd,n) {}    //use class names for inheritance

3)访问基类的方法

  包含使用对象来调用方法:

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

私有继承使得能够使用类名和作用域解析运算符来调用基类的方法:

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

4)访问基类对象

例如,Student类的包含版本实现了Name()方法,它返回string对象成员name;但使用私有继承时,该str

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值