C++程序设计第10章 继承.docx
- 文档编号:18003737
- 上传时间:2023-04-24
- 格式:DOCX
- 页数:38
- 大小:155.28KB
C++程序设计第10章 继承.docx
《C++程序设计第10章 继承.docx》由会员分享,可在线阅读,更多相关《C++程序设计第10章 继承.docx(38页珍藏版)》请在冰豆网上搜索。
C++程序设计第10章继承
第10章继承(Inheritances)
继承是C++语言的一种重要机制,该机制使类与类之间可以建立一种上下级关系,可以自动地提供来自另一个类的操作和数据结构来创建新类,程序员只需在新类中定义已有类中没有的成分来建立新类。
继承是面向对象程序设计的重要基础。
10.1继承结构(InheritantStructures)
1类层次结构(ClassHierarchies)
图10_01展示了交通工具的类层次,最顶部的交通工具类称为基类。
这个基类有飞机类,汽车类和火车类,交通工具类就是它们的父类。
还可以从交通工具类派生(derived)出其他类,例如,轮船类等。
每个类都只以交通工具类作为其父类。
汽车类相对于交通工具类来说是子类,所以,在本图的类系中,也可以称汽车子类。
汽车子类还有三个子类,小汽车类,大卡车类,大客车类,每个子类都以汽车类作为父类,此时的交通工具类则是它们的祖先类,简称祖类。
另外,小汽车类派生了轿车类,工具车类和小面包车类。
图中展示了小型的5个层次的类系,从上到下它们是派生的关系,从下到上是继承的关系。
每个类都有且只有一个父类,除了最顶层的交通工具类,其他所有的类都可以是子类,当一个类派生出其他类的时候,自己便是父类了。
继承关系使得我们得以用一种简单的方式来描述事物。
例如,描述什么叫鸭子,可以回答说,它是一种嘎嘎叫的鸟。
鸭子是一种鸟,所以鸭子是鸟类的派生,但鸭子又具有嘎嘎叫的特征,嘎嘎叫是区别于其他同类鸟的属性。
由于鸟类通常的特征大家都清楚,例如,有翅膀,有两只脚等,所以用鸟类来描述鸭子,只要举出鸭子自己所具有的特点就行了。
继承使我们描述事物的能力大大增强和直截了当。
描述事物,一般是从属性和操作上来描述的,例如,日期具有年、月、日的属性,显示日期,闰年判断都可以认为是日期所具有的操作。
把这种继承关系引入程序设计,目的是希望过去描述(定义)的类能够作为基类,来进一步详细地描述派生的事物。
这样一来,派生事物的描述基于基类,就可以简单化了。
对于一个问题的解决,事先有一些基类,即一些资源,这些基类,已经具有一定的数据描述和较强的数据操作能力了,籍此,通过简单描述事物的属性和操作,就可以继承基类的强大功能,为我所用,方便程序设计了。
继承就是让子类继承父类的属性和操作,子类可以声明新的属性和操作,还可以剔除那些不适合其用途的父类操作。
在新的应用中,父类的代码已经存在,无须修改父类。
所要做的是派生子类,在子类中增加和修改。
所以,继承可以让你重用父类的代码,专注于为子类编写新代码。
在没有采用继承技术之前,程序重用的是过程代码,或者说操作,例如C语言所附的库函数便是一种编程资源,提供给我们一定程度的过程代码重用。
现实世界是分类分层的客观实在,物质有无机与有机之分,有机体有生命体与非生命体之分,生命体有动物,植物,微生物之分,动物有高等与低等,人是高等动物,人有各个种族,……
继承也是我们理解事物,解决问题的方法,继承帮助我们描述事物的层次关系,帮助我们如何有效地精确地描述事物,帮助我们理解事物直至本质。
一旦看清了事物所处的层次结构位置,也就可以找到相关的解决办法。
继承可以使已经存在的类不需修改地适应新应用,继承是比过程重用规模更广的重用,是已经定义的良好的类的重用。
2对象本体(ObjectReality)
如果类BaseClass是基类:
classBaseClass{
inta,b;
//otherprivatemembers
public:
//publicmembers
};
则其对象本体含有两个整型空间。
派生类继承的方式是在类定义的class类名的后面加上:
public再加上基类名。
如果B继承了BaseClass类,则:
classB:
publicBaseClass{
intc;
//otherprivatemembers
public:
//publicmembers
};
派生类对象本体包括两个部分,一个为基类部分,即含两个整型空间,另一个为派生类部分,含一个整型空间。
如图10_02所示。
这是一个示意图,表示派生类与基类不可分割的关系,派生类总是依附于基类,派生类对象中总是含有基类对象,即含有基类的数据成员。
或者说,基类对象是派生类对象的组成部分。
至于具体的实现中,空间的安排,并不一定基类排在前,派生类排在后。
显然,派生类对象通常比基类对象大,它保存了更多的数据,提供了更多的操作。
基类也称超类,派生类也称子类,读者必须接受超类的数据反而比子类的数据少这个事实。
10.2成员函数(MemberFunction)
1继承父成员(InheritFather’sMember)
在类中,还有一种保护(protected)型的访问符,保护成员与私有成员一样,不能被使用类的程序员进行公共访问,可以被类内部的成员函数访问,除此之外,如果使用类者是派生类成员,则可以被访问,这是私有成员所不具有的能力。
也就是说,只要将类成员声明成保护成员,则其派生类在继承之后,就可以坐享其父类的公有和保护操作了。
例如,有一个学生类Student,现在要增加研究生类,研究生类除了自己所特有的性质外,具有学生类的所有性质,所以我们用继承的方法来重用学生类:
1.//=====================================
2.//f1001.cpp
3.//inheritance
4.//=====================================
5.#include
6.usingnamespacestd;
7.//-------------------------------------
8.classAdvisor{//导师
9.intnoOfMeeting;
10.};//-----------------------------------
11.classStudent{
12.stringname;
13.intsemesterHours;
14.doubleavge;
15.public:
16.Student(stringpName="noName"):
name(pName),average(0),semesterHours(0){}
17.voidaddCourse(inthours,doublegrade){
18.doubletotalGrade=(semesterHours*average+grade);//总分
19.semesterHours+=hours;//总修学时
20.average=semesterHours?
totalGrade/semesterHours:
0;//平均分
21.}
22.voiddisplay(){
23.cout<<"name=\""< 24.<<",average="< 25.} 26.intgetHours(){returnsemesterHours;} 27.doublegetAverage(){returnaverage;} 28.};//----------------------------------- 29.classGraduateStudent: publicStudent{ 30.Advisoradvisor; 31.intqualifierGrade; 32.public: 33.getQualifier(){returnqualifierGrade;} 34.};//----------------------------------- 35.intmain(){ 36.Studentds("Loleeundergrade"); 37.GraduateStudentgs; 38.ds.addCourse(3,2.5); 39.ds.display(); 40.gs.addCourse(3,3.0); 41.gs.display(); 42.}//==================================== ds是Student类对象,gs是GraduateStudent类对象。 作为Student的子类,对象gs可以做ds能做的任何事情,它有name,semesterHours,average数据成员,以及addCourse()成员函数,此外它还比ds多一点东西,即它有导师Advisor和资格考试分qualifierGrade。 如果GraduateStudent类不继承Student类,则gs对象中就没有ds成分,即学时和平均分数据成员都没有,也不能以gs的名义进行addCourse操作。 若要使用addCourse操作,则必须以Student对象的名义。 可见,没有继承的研究生类对象必须将Student类拿来,对里面的关键代码进行复制,重新编写和组织类,这种借鉴作用,比完全拿来重用,要落后很多。 何况玩真格儿的规模化程序设计还没有开始,彼此之间相差的工作量真不敢说。 现在,gs对象也是一个学生,所以对Student中的addCourse()成员函数的调用,等于是在调用自己的成员函数。 正是由于gs是一个学生,所以,将gs赋值给Student对象也是合情合理的。 因为gs也能做Student对象所能做的任何事。 即: GraduateStudentgs; Students(gs);//ok Student&t=gs;//ok Student*t=&gs;//ok 事实上,gs的对象实体中包含有Student对象实体。 将gs赋值给Student对象s,就是将gs中的Student对象实体部分,拷贝给s。 将gs初始化Student对象的引用t,就是将t作为gs中的Student对象实体的别名。 因此,以基类对象作形参,以派生类对象作为实参的函数调用,也是合理的设计。 例如,将研究生对象传递给学生类对象的引用: voidfn(Student&s){ //任何s想要做的事 } voidgn(){ GraduateStudentgs; fn(gs); } 2类内访问控制(AccessControlinClass) 继承可以公共继承,也可以保护继承和私有继承。 多数情况是公有继承,就像前面所看到的。 也就是说,在class类名后面加上public关键字再加基类名称。 对于保护继承和私有继承,见CH15.6。 公共继承,反映了派生类对基类所有成员原封不动的访问控制权限的继承。 公有和保护操作的继承。 和派生类之间的 继承了基类,并不是说派生类就能访问基类的私有成员了。 如果是那样的话,那些使用基类的人,靠派生,就能使用基类的私有成员了: classBase{ inta; public: voidprint(){cout< //publicmembers }; classDerived: publicBase{ intb; public: voiddisplay(){cout< //otherpublicmembers }; voidfn(){ Derivedd; d.print();//ok d.display();//能访问Base类的私有成员吗? cout< } 这样一来,本来任何由基类引起的错误,就并不一定是由基类自己引起的了,有可能是其后裔捣鬼,程序调试因而变得复杂起来了。 而且类变得一点隐私都没有了,使用类者想用类的私有数据,只要轻言继承,就能访问基类的一切。 类机制一方面通过访问控制提供屏蔽类,分离类的实现的能力,使得编程职责分离,另一方面却又允许继承的子女毫无遮挡地访问其私有成员,等于让人人都可以越过访问控制而去访问私有成员,这是类机制肯定不能允许的。 一个类,将外界能够访问的操作都公有化了,所有不能被外界访问的成员都私有化,这样一来,在后继的类中,就没有对基类任何可以悄悄改进的余地了。 所以,继承也需要这样的成员,它们对外界是私有的,对派生的子女是允许访问的。 这种设计需求就是访问控制符protected。 classBase{ inta; voidf(){cout< public: intb; voidg(){cout< protected: intc; voidk(){cout< };//----------------------------------- classDerived: publicBase{ public: voiddf(){
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C+程序设计第10章 继承 C+ 程序设计 10