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


doubleStudent::Average()const{if(scores.size()>0)returnscores.sum()/scores.size();elsereturn0;}然而 , 私有继承使得能够使用类名和作用域解析运算符来调用基类的方法:
doubleStudent::Average()const{if(ArrayDb::size()>0)returnArrayDb::sum()/ArrayDb::size();elsereturn0;}总之 , 使用包含时将使用对象名来调用方法 , 而使用私有继承时将使用类名和作用域解析运算符来调用方法 。
3.访问基类对象使用作用域解析运算符可以访问基类的方法 , 但如果要使用基类对象本身 , 该如何做呢?例如 , Student类的包含版本实现了Name()方法 , 它返回string对象成员name;但使用私有继承时 , 该string对象没有名称 。 那么 , Student类的代码如何访问内部的string对象呢?
答案是使用强制类型转换 。 由于Student类是从string类派生而来的 , 因此可以通过强制类型转换 , 将Student对象转换为string对象;结果为继承而来的string对象 。 本书前面介绍过 , 指针this指向用来调用方法的对象 , 因此*this为用来调用方法的对象 , 在这个例子中 , 为类型为Student的对象 。 为避免调用构造函数创建新的对象 , 可使用强制类型转换来创建一个引用:
conststring&Student::Name()const{return(conststring&)*this;}上述方法返回一个引用 , 该引用指向用于调用该方法的Student对象中的继承而来的string对象 。
4.访问基类的友元函数用类名显式地限定函数名不适合于友元函数 , 这是因为友元不属于类 。 然而 , 可以通过显式地转换为基类来调用正确的函数 。 例如 , 对于下面的友元函数定义:
ostream&operator<如果plato是一个Student对象 , 则下面的语句将调用上述函数 , stu将是指向plato的引用 , 而os将是指向cout的引用:
cout<<plato;下面的代码:
os<<"Scoresfor"<<(conststring&)stu<<":n";显式地将stu转换为string对象引用 , 进而调用函数operator<
引用stu不会自动转换为string引用 。 根本原因在于 , 在私有继承中 , 未进行显式类型转换的派生类引用或指针 , 无法赋值给基类的引用或指针 。
然而 , 即使这个例子使用的是公有继承 , 也必须使用显式类型转换 。 原因之一是 , 如果不使用类型转换 , 下述代码将与友元函数原型匹配 , 从而导致递归调用:
os<<stu;另一个原因是 , 由于这个类使用的是多重继承 , 编译器将无法确定应转换成哪个基类 , 如果两个基类都提供了函数operator<
程序清单14.5studenti.cpp
//studenti.cpp--Studentclassusingprivateinheritance#include"studenti.h"usingstd::ostream;usingstd::endl;usingstd::istream;usingstd::string;//publicmethodsdoubleStudent::Average()const{if(ArrayDb::size()>0)returnArrayDb::sum()/ArrayDb::size();elsereturn0;}conststring&Student::Name()const{return(conststring&)*this;}double&Student::operator[](inti){returnArrayDb::operator[](i);//useArrayDb::operator[]()}doubleStudent::operator[](inti)const{returnArrayDb::operator[](i);}//privatemethodostream&Student::arr_out(ostream&os)const{inti;intlim=ArrayDb::size();if(lim>0){for(i=0;i<lim;i++){os<<ArrayDb::operator[](i)<<"";if(i%5==4)os<<endl;}if(i%5!=0)os<<endl;}elseos<<"emptyarray";returnos;}//friends//useStringversionofoperator>>()istream&operator>>(istream&is,Student&stu){is>>(string&)stu;returnis;}//usestringfriendgetline(ostream&,conststring&)istream&getline(istream&is,Student&stu){getline(is,(string&)stu);returnis;}//usestringversionofoperator<同样 , 由于这个示例也重用了string和valarray类的代码 , 因此除私有辅助方法外 , 它包含的新代码很少 。