实验五类的继承与派生.docx
- 文档编号:11137354
- 上传时间:2023-02-25
- 格式:DOCX
- 页数:19
- 大小:27.51KB
实验五类的继承与派生.docx
《实验五类的继承与派生.docx》由会员分享,可在线阅读,更多相关《实验五类的继承与派生.docx(19页珍藏版)》请在冰豆网上搜索。
实验五类的继承与派生
第一节类的继承与派生
一、基本概念
继承是面向对象程序设计的一个特性,所谓继承就是在已有类的基础上创建新的类,新类可以从一个或多个已有类中继承成员函数或数据成员,而且新类还可以重新定义或加进新的数据和函数。
其中,已有类称为基类或父类,新类称为派生类或子类。
在现实世界中许多事物都具有继承性。
例如:
“汽车”这个类中包括了许多类型,有运输汽车、专用汽车;运输汽车中又包括客车、货车…….;专用汽车中又包括巡逻车、消防车、救护车……..;所有这些类型的车都具有汽车的共同特性即都有发动机、车身、轮胎等共性,还都是自行驱动的。
而客车和货车又有所不同,客车用来载客,货车用来拉货,它们有自己不同于其它车的特性,这就是继承。
我们把汽车称为基类,把运输汽车、客车、货车称为派生类。
通过继承,派生类不仅拥有了基类的属性和行为,而且具有不同于它类的自己的特点。
二、派生类的定义与构成
当你去水果店买水果的时候,你经常会发现很多同类水果又有了新的品种。
比如,“李子”既小又涩,嫁接在梨树上后长出来的李子却硕大、香甜、清脆,比没有嫁接的李子好吃,但它还是李子家族中的一员;所以,可以认为“嫁接李子”是从“李子”中派生出来的。
当然,可以把“李子”嫁接在梨树上,也可以嫁接在苹果树上,结出来的都是“李子”,但是各自味道不同。
所谓派生就是从已有类中产生一个新的子类。
基类就是已存在的可以派生新类的类,如下图中的A、D、E都是基类。
派生类就是由基类派生出来的新类,如下图中的B、C、F都是派生类。
1.单继承派生类的定义格式
class<派生类名>:
<继承方式><基类名>
{
派生类成员的定义;
};
其中,“派生类名”是新定义的一个类的名字,它是从“基类名”中派生的,并且按指定的“继承方式”派生。
例如:
classpeach//基类
{
datatypecolor,shape;
};
classsweetpeach:
publicpeach//单继承
{
datatypecolor,shape,taste;
};
sweetpeach类只是继承自peach类,即sweetpeach类只有一个基类,这就是单继承。
2.多继承派生类的定义格式
class<派生类名>:
<继承方式1><基类名>,<继承方式2><基类名>,…….
{
派生类成员的定义;
};
多继承与单继承在定义格式的区别仅在于它们的基类个数不同,单继承的基类只有一个,而多继承的基类有多个,相邻两个基类之间用逗号间隔,每个基类名前都应有一个该基类的继承方式的说明符。
例如:
classpeach//定义基类:
peach
{
datatypecolor,shape;
};
classapple//定义基类:
peach
{
datatypecolor,shape,weight;
};
classsweetpeach:
publicpeach,publicapple//多继承
{
datatypecolor,shape,taste;
};
类sweetpeach同时继承自类peach和类apple,这就是多继承。
3.继承的作用
有的读者可能会问为什么要有继承,继承有什么好处,继承的作用是什么?
为了解决这些疑问,我们一起来分析以下例子,从中领悟继承的奥妙。
【例10-1-1】分析以下代码。
声明一个person类,它包含的成员有name(姓名)、age(年龄)、gender(性别),和output函数,具体定义如下:
classperson
{
public:
charname[8];
intage;
chargender;
public:
voidoutput(){}
};
现在要声明一个student类,它包含的成员有name(姓名),age(年龄),gender(性别),department(系),stuno(学号),address(住址),和output函数,具体定义如下:
classstudent
{
public:
charname[8];
intage;
chargender;
chardepartment[20];
intstuno;
intaddress;
public:
voidoutput(){}
};
从这两个类的声明中可以看出,它们中有些成员数据和成员函数是相同的。
这样就存在代码的重复,为了提高代码的可重用性,就引入了继承。
即,如果student类以共有继承的方式继承person类,那么student类就可以直接使用person类中的共有成员如name,gander,age和output()函数,这样在student类中就不需要再定义与person类中相同的变量了,只定义person类中没有的在student类中需要的变量。
具体实现如下:
classstudent:
publicperson//student共有继承person类
{
public:
chardepartment[20];
intstuno;
intaddress;
public:
voidoutput(){}
};
提示
Ø student类称为派生类,person类成为基类;
Ø 关键字public的作用是说明派生类公有继承了基类中的所有成员,即派生类可以直接访问基类的成员;
Ø 继承可以使代码得以重用,提高工作效率。
三、派生类访问基类成员
通过前面的学习大家都知道基类的成员有public(公有)、protected(保护)、private(私有)3种访问属性,基类的自身成员可以对基类中任何一个其他成员进行访问,但是通过基类的对象就只能访问该类的公有成员。
派生类可以继承基类中除了构造函数和析构函数之外的全部成员,但是这些成员的访问属性在派生过程中是可以调整的。
从基类继承来的成员在派生类中的访问属性是由继承方式控制的。
不同的继承方式导致原来具有不同的访问属性的基类成员在派生类的访问属性也有所不同。
在派生类中,从基类继承来的成员可以访问属性有4种:
不可直接访问的成员、public(公有成员)、protected(保护成员)、private(私有成员)。
1.三种继承方式的声明
public公有继承
公有继承:
在定义一个派生类时将基类的继承方式指定为public的继承方式。
例如:
classstudent:
publicperson{}
private私有继承
私有继承:
在定义一个派生类时将基类的继承方式指定为private的继承方式。
例如:
classstudent:
privateperson{}
protected保护继承
保护继承:
在定义一个派生类时将基类的继承方式指定为protected的继承方式。
例如:
classstudent:
protectedperson{}
2.三种继承方式的区别
如表1指明了三种继承方式的区别,即派生类对基类成员的访问能力。
表1三种继承方式的区别
在基类中的访问属性
继承方式
在派生类中的访问属性
private
public
不可直接访问
private
private
不可直接访问
private
protected
不可直接访问
public
public
public
public
private
private
public
protected
protected
protected
public
protected
protected
private
private
protected
protected
protected
提示
Ø 在任何继承方式中基类中的私有成员都不允许派生类继承,即在派生类中是不可直接访问基类中的私有成员。
Ø 当类的继承方式为公有继承时:
基类中的所有公有成员在派生类中仍为公有成员;基类中的所有保护成员在派生类中仍为保护成员。
Ø 当类的继承方式为私有继承时:
基类中的所有公有成员在派生类中都为私有成员;基类中的所有保护成员在派生类中都为私有成员。
Ø 当类的继承方式为保护继承时:
基类中的所有公有成员在派生类中都为保护成员;基类中的所有保护成员在派生类中仍为保护成员。
派生类对基类成员的访问形式主要有以下两种:
(1)内部访问:
由派生类中的新增成员对从基类继承来的成员的访问。
(2)对象访问:
在派生类外部,通过派生类的对象对从基类继承的成员的访问。
现在分别讨论在公有继承、私有继承、保护继承这3种继承方式下,派生类对基类成员的访问规则。
一、公有继承
【例1】分析以下程序。
源代码:
#include
#include
classBase
{
private:
intpvx;//pvx为基类私有变量
protected:
intpty;//pty为基类保护变量
public:
floatpuf;//puf为基类公有变量
voidSetxy(intq,intu,floatw)//Setxy()为基类公有函数
{
pvx=q;pty=u;puf=w;
}
voidOutput()//Output()为基类公有函数
{
cout<<"classBaseoutput"< cout<<"pvx="< cout<<"pty="< cout<<"puf="< } }; classDerive: publicBase//公有单继承 { private: floatpvz; public: voidSetvalue(intx,inty,floatf,floatz) { Setxy(x,y,f); pvx=x;//非法访问,基类中的pvx为private属性,不能被继承 pty=y;//合法访问 puf=f;//合法访问 pvz=z; } voidPrint() { cout<<"pvx="< cout<<"classDeriveoutput"< cout<<"pty="< cout<<"puf="< cout<<"pvz="< } }; voidmain() { Deriveobj; obj.Setvalue(3,5,8.9,12.6); obj.Output(); obj.Print(); cout<<"puf="< cout< system("pause"); } 运行输出: classBaseoutput pvx=3 pty=5 puf=8.9 classDeriveoutput pty=5 puf=8.9 pvz=12.6 puf=8.9 【简要分析】 ①“classDerive: publicBase{}”表明这是一个公有继承的例子,基类Base中有3个变量和两个函数: 私有变量pvx、保护变量pty、公有变量puf和公有函数Setxy()、Output()。 其中: 被Derive派生类继承后,pvx在派生类中不能直接访问,只能通过Base中具有public属性的函数对其间接访问;pty被Derive派生类继承之后仍为protected属性,派生类成员可以直接访问;puf、Setxy()、Output()这3个具有public属性成员被Derive派生类继承后,仍为public属性,派生类成员可以对其直接访问。 ②输出的前4行: 调用“obj.Output();”的输出结果。 输出的后4行: 调用“obj.Print();”的输出结果。 最后1行: 调用“cout<<"puf="< 结论: 在公有继承中,无论是派生类中的成员还是派生类对象都不能直接访问基类中的private成员;派生类的成员可以访问继承来的protected成员和public成员;但是,类的外部使用者只能通过派生类的对象访问继承来的public成员,不能访问继承于基类的private和protected成员。 二、私有继承 【例2】任务1: 分析以下程序。 a)找出非法语句并在程序中注释非法的原因。 b)写出删除非法语句后程序的运行结果。 源代码: #include #include classBase { private: intpvx; protected: intptf; public: voidSetxf(intw,intf) { pvx=w;ptf=f; } voidPrint() { cout<<"pvx="< cout<<"ptf="< } }; classDerive: privateBase//私有继承 { private: doublepvy; protected: doubleptz; public: intpd; voidSetvalue(inta,intb,doublec,doubled) { pvx=a; ptf=b+6; Setxf(a,b); pvy=c; ptz=d; pd=90; } voidOutput() { cout<<"pvx="< Print(); cout<<"pvy="< cout<<"ptz="< } }; voidmain() { Deriveobj; obj.Setvalue(1,6,5.3,3.8); obj.Output(); obj.Setxf(101,87); cout<<"pvx="< cout<<"pvy="< cout<<"ptz="< obj.pd=68; cout<<"pd="< system("pause"); } 【简要分析】 “classDerive: privateBase{}”表明这是一个私有继承,Base基类中有3个变量和两个函数: 私有pvx、保护ptf、公有函数Setxf()、公有函数Print()。 基类Base被私有继承之后,其protected成员在派生类中不能直接访问;而protected成员和public成员都成了派生类的私有成员,只有派生类的成员才能直接访问;派生类对象也不能直接访问继承自Base的protected成员和public成员。 结论: 私有继承中,基类中的protected、public成员都成为派生类中的private成员,派生类成员不能直接访问基类中的private成员,而派生类中的成员可以直接访问基类中的protected、public属性的成员;派生类对象不能直接访问基类中的任何成员。 三、保护继承 【例3】任务2: 分析以下程序。 a)找出非法语句并在程序中注释非法的原因。 b)写出删除非法语句后程序的运行结果。 源代码: #include #include classBase { private: intpvx; protected: intpty; public: intpuz; voidsetx(inta) { pvx=a; } intgetx() { returnpvx; } }; classDerive: protectedBase//保护继承 { private: intpva; protected: intptb; public: intpuc; voidsetvalue(inta,intb,intc,intd,inte,intf) { pvx=a; setx(a); pty=b; puz=c; pva=d; ptb=e; puc=f; } voidprint() { cout<<"pvx="< cout<<"pty="< cout<<"puz="< cout<<"pva="< cout<<"ptb="< cout<<"puc="< } }; voidmain() { Deriveobj; obj.setvalue(9,8,7,6,5,4); obj.print(); cout<<"puc="< system("pause"); } 结论: 保护继承中,基类中的protected、public成员都成为派生类中的protected成员,派生类成员不能直接访问基类中的private成员,而派生类中的成员可以直接访问基类中的protected、public属性的成员;派生类对象均不能直接访问基类中的任何成员。 【例4】任务3: 分析以下程序。 找出非法语句并在程序中注释非法的原因。 分析以下代码。 源代码: #include usingnamespacestd; classperson { public: charname[8]; chargender; voidshow() {cout< private: intage; protected: charaddress[20]; }; classteacher: publicperson//公有继承 { private: chartecpost[8]; chardepartment[20]; public: voidputout() { cout< cout< cout< } }; classstudent: protectedperson//保护继承 { public: charstuno[15]; charschool[20]; voidputout() { cout< cout< cout< } }; classdoctor: privateperson//私有继承 { public: chartel[13]; charposition[15]; voidputout() { cout< cout< cout< } }; voidmain() { teachera; studentb; doctorc; cout< cout< cout< cout< cout< cout< cout< } (注: 可编辑下载,若有不当之处,请指正,谢谢! )
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 继承 派生