星球狂想战队|一起来学C++:C++中的代码重用( 七 )
5.使用修改后的Student类接下来也需要测试这个新类 。 注意到两个版本的Student类的公有接口完全相同 , 因此可以使用同一个程序测试它们 。 唯一不同的是 , 应包含studenti.h而不是studentc.h , 应使用studenti.cpp而不是studentc.cpp来链接程序 。 程序清单14.6列出列该程序 , 请将其与studenti.cpp一起编译 。
程序清单14.6use_stui.cpp
//use_stui.cpp--usingaclasswithprivateinheritance//compilewithstudenti.cpp#include#include"studenti.h"usingstd::cin;usingstd::cout;usingstd::endl;voidset(Student&sa,intn);constintpupils=3;constintquizzes=5;intmain(){Studentada[pupils]={Student(quizzes),Student(quizzes),Student(quizzes)};inti;for(i=0;i<pupils;i++)set(ada[i],quizzes);cout<<"nStudentList:n";for(i=0;i<pupils;++i)cout<<ada[i].Name()<<endl;cout<<"nResults:";for(i=0;i<pupils;i++){cout<<endl<<ada[i];cout<<"average:"<<ada[i].Average()<<endl;}cout<<"Done.n";return0;}voidset(Student&sa,intn){cout<<"Pleaseenterthestudent'sname:";getline(cin,sa);cout<<"Pleaseenter"<<n<<"quizscores:n";for(inti=0;i<n;i++)cin>>sa[i];while(cin.get()!='n')continue;}下面是该程序的运行情况:
Pleaseenterthestudent'sname:GilBaytsPleaseenter5quizscores:9294969395Pleaseenterthestudent'sname:PatRoonePleaseenter5quizscores:8389727895Pleaseenterthestudent'sname:FleurO’DayPleaseenter5quizscores:9289967464StudentList:GilBaytsPatRooneFleurO'DayResults:ScoresforGilBayts:9294969395average:94ScoresforPatRoone:8389727895average:83.4ScoresforFleurO'Day:9289967464average:83Done.输入与前一个测试程序相同 , 输出也相同 。
14.2.2使用包含还是私有继承由于既可以使用包含 , 也可以使用私有继承来建立has-a关系 , 那么应使用种方式呢?大多数C++程序员倾向于使用包含 。 首先 , 它易于理解 。 类声明中包含表示被包含类的显式命名对象 , 代码可以通过名称引用这些对象 , 而使用继承将使关系更抽象 。 其次 , 继承会引起很多问题 , 尤其从多个基类继承时 , 可能必须处理很多问题 , 如包含同名方法的独立的基类或共享祖先的独立基类 。 总之 , 使用包含不太可能遇到这样的麻烦 。 另外 , 包含能够包括多个同类的子对象 。 如果某个类需要3个string对象 , 可以使用包含声明3个独立的string成员 。 而继承则只能使用一个这样的对象(当对象都没有名称时 , 将难以区分) 。
然而 , 私有继承所提供的特性确实比包含多 。 例如 , 假设类包含保护成员(可以是数据成员 , 也可以是成员函数) , 则这样的成员在派生类中是可用的 , 但在继承层次结构外是不可用的 。 如果使用组合将这样的类包含在另一个类中 , 则后者将不是派生类 , 而是位于继承层次结构之外 , 因此不能访问保护成员 。 但通过继承得到的将是派生类 , 因此它能够访问保护成员 。
另一种需要使用私有继承的情况是需要重新定义虚函数 。 派生类可以重新定义虚函数 , 但包含类不能 。 使用私有继承 , 重新定义的函数将只能在类中使用 , 而不是公有的 。
提示:
通常 , 应使用包含来建立has-a关系;如果新类需要访问原有类的保护成员 , 或需要重新定义虚函数 , 则应使用私有继承 。
14.2.3保护继承保护继承是私有继承的变体 。 保护继承在列出基类时使用关键字protected:
classStudent:protectedstd::string,protectedstd::valarray{...};使用保护继承时 , 基类的公有成员和保护成员都将成为派生类的保护成员 。 和私有继承一样 , 基类的接口在派生类中也是可用的 , 但在继承层次结构之外是不可用的 。 当从派生类派生出另一个类时 , 私有继承和保护继承之间的主要区别便呈现出来了 。 使用私有继承时 , 第三代类将不能使用基类的接口 , 这是因为基类的公有方法在派生类中将变成私有方法;使用保护继承时 , 基类的公有方法在第二代中将变成受保护的 , 因此第三代派生类可以使用它们 。
推荐阅读
- 游戏小怪兽|达仁星球:最新抖音直播留人控场方法和技巧
- 巅峰战队|VERTIX户外手表,勇攀新高峰——COROS
- 星球狂想战队|世界科技格局
- 家族战队|10年后退化成了“简陋版”,快看丨腾讯微博将于9月28日停服
- 路人战队|失去苹果的代价,有300万人承担不起,请别口嗨“抵制苹果”了
- 家族战队|就读懂了湖南互联网产业,读懂了这些话
- 路人战队|雷军用了什么法宝?,超越格力?新型洗烘一体机实现“弯道超车”
- NASA|NASA发现“黄金星球”,价值超万万亿美元,美国已准备前往
- 天文在线|既有大气又有水 宝藏星球土卫六,宇宙中的超级泰坦
- 通天战队|别人偷动你手机,屏幕就会一戳一个洞,只有你可以打开,教你一招