版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1 第第6章章 单继承类单继承类 v本章内容:本章内容: f6.1单继承类 f6.2派生控制 f6.3成员访问 f6.4构造与析构 f6.5父类和子类 f6.6派生类的存储空间 2 6.1单继承类单继承类 v继承继承是c+类型演化的重要机制,在保留原有类 的属性和行为的基础上,派生出的新类可以有 某种程度的变异。 v通过继承,新类自动具有了原有类的属性和行 为,因而只需定义原有类型没有的新的数据成 员和函数成员。实现了软件重用,使得类之间 具备了层次性层次性。 v通过继承和派生形成的类蔟,反映了面向对象 问题域、主题等概念,形成类似java的包。 3 point int visible; po
2、int(int x,int y); point( ); int show( ); int hide( ); int isvisible( ); void moveto(int x,int y); 6.1单继承类单继承类 v点具有可见性,并具有x ,y坐标特性,可以移动。 point int x, y; int visible; point(int x,int y, int visible); point( ); int getx( ); int gety( ); void setx(int x); void sety(int y); void show( ); void hide( ); in
3、t isvisible( ); void moveto(int x,int y); location int x, y; location(int x,int y); location( ); int getx( ); int gety( ); void setx(int x); void sety(int y); void moveto(int x,int y); 继承继承 派生派生 point int x, y; int visible; point(int x,int y, int visible); point( ); int getx( ); int gety( ); void sh
4、ow( ); void hide( ); int isvisible( ); void moveto(int x,int y); 4 6.1单继承类单继承类 v派生类与基类派生类与基类:接受成员的新类称为派生类, 如上例中的point类;提供成员的类称为基类, 如上例中的location类。 f基类是对若干个派生类的抽象,取了派生类的公共 特征;而派生类是基类的具体化,通过增加属性或 行为将基类变为某种更有用的类型。 f派生类可以看作基类定义的延续,先定义一个抽象 基类,该基类中有些操作并未实现;然后定义非抽 象的派生类,实现抽象基类中未实现的操作。 5 6.1单继承类单继承类 vc+通过多种
5、控制派生的方法获得新的派生类: 添加新的数据成员和函数成员; 改变继承来的基类成员的访问权限; 恢复继承来的基类成员的访问权限; 重新定义同名的函数成员。 v单继承与多继承: f派生类可以接受一个基类提供的数据成员和函数成 员,也可以接受多个基类提供的数据成员和函数成 员,这两种继承形式分别称为单继承单继承和多继承多继承。 f多继承中的派生类有多于一个的基类,这时派生类 将是所有基类行为的组合。 6 6.1单继承类单继承类 v单继承的定义格式单继承的定义格式: fclass : ; f指明派生类采用什么继承方式从基类 获得成员,分为三种:private表示私有基类; protected表示保护
6、基类;public表示公有基类。 注意区别派生控制和访问控制。 7 6.1单继承类单继承类 【例【例6.1、6.2】分别定义定位坐标】分别定义定位坐标location类和其派生类和其派生 的点的点point类。类。 #include class location/定义定位坐标类定义定位坐标类 int x,y; public: int getx( ); int gety( );/获得当前坐标获得当前坐标 void moveto(int x,int y);/定义移动坐标函数成员定义移动坐标函数成员 location(int x,int y); location( ); ; void locatio
7、n:moveto(int x,int y) location:x=x; location:y=y; int location:getx( ) return x; int location:gety( ) return y; 8 6.1单继承类单继承类 location:location(int x,int y) location:x=x; location:y=y; location:location( ) class point:public location /定义点类,从定义点类,从location类继承,派生控制为类继承,派生控制为public int visible;/新增可见属性新
8、增可见属性 public: int isvisible( ) return visible; /新增函数成员新增函数成员 void show( ),hide( ); void moveto(int x,int y);/重新定义与基类同名函数重新定义与基类同名函数 point(int x,int y):location(x,y) visible=0; /在构造派生类对象前先构造基类对象在构造派生类对象前先构造基类对象 point( ) hide( ); ; void point:show( ) visible=1; 9 6.1单继承类单继承类 putpixel(getx( ),gety( ),g
9、etcolor( ); void point:hide( ) visible=0; putpixel(getx( ),gety( ),getbkcolor( ); void point:moveto(int x,int y) int v=isvisible( ); if(v) hide( ); location:moveto(x,y); if(v) show( ); void main(void) point p(3,6); p.location:moveto(7,8); /调用基类调用基类moveto函数函数 p.moveto(9,18);/调用派生类调用派生类moveto函数函数 带类名访
10、问基类的带类名访问基类的moveto函函 数,如果不带类名会导致无数,如果不带类名会导致无 休止的递归调用。休止的递归调用。 问题问题:调用基类:调用基类moveto函数函数 会导致什么问题?会导致什么问题? 10 6.1单继承类单继承类 v说明说明: f用class声明的类的派生控制缺省为private,因此, 声明class point: private location等价于声明class point: location。 f派生类也可以用struct声明,不同之处在于:用struct 声明的派生控制和访问权限缺省为public。 f用union声明的类既不能作基类,也不能作任何基类 的
11、派生类。 当基类成员被继承到派生类时,该成员在派生类中的访 问权限由派生控制决定。必须慎重的选择派生控制,它 是面向对象程序设计的一个非常重要的环节 11 6.2派生控制派生控制 v派生类可以有三种继承方式:公有继承public、 保护继承protected、私有继承private。 公有继承:基类的公有成员和保护成员派生 到派生类时,都保持原有的状态; 保护继承:基类的公有成员和保护成员派生 后都成为派生类的保护成员; 私有继承:基类的公有成员和保护成员派生 后都作为派生类的私有成员。 12 6.2派生控制派生控制 v基类的私有成员同样也被继承到派生类中,构 成派生类的一个组成部分,但对派生
12、类函数成 员不可见,派生类函数成员也不能访问。 f若派生类函数成员要访问这一组成部分,则必须将 其声明为基类的成员友元。 v在派生类外部对其成员访问的权限: f对于新定义成员,按定义时的访问权限访问; f对于继承来的基类成员,取决于这些成员在派生类 中的访问权限,与其在基类中定义的访问权限无关。 13 6.2派生控制派生控制 v基类成员继承到派生类时,其访问权限的变化同 派生控制有关。 f假定访问权限和派生控制满足private protected val!=v) h=h-next; return h!=0; 【例【例6.3】以链表】以链表list类为基类定义集合类类为基类定义集合类set。
13、23 6.3 成员访问成员访问 int list:insert(int v)/在链表中插入新增节点在链表中插入新增节点 if(contains(v) return 0; head=new node(v,head); return 1; class set:protected list/采用保护继承方式采用保护继承方式 int used;/集合元素的个数集合元素的个数 public: list:contains; /恢复恢复contains函数访问权限函数访问权限 int insert(int); /需要改变需要改变used值,因此改写值,因此改写insert函数函数 set( ) ; ; in
14、t set:insert(int v) /list:insert中的中的list不能省略:否则自递归不能省略:否则自递归 if(!contains(v) return 0; void main(void) set s; 24 6.3 成员访问成员访问 v 派生类不能访问基类私有成员,除非将派生类的声明为 基类的友元类,或者将要访问基类私有成员的派生类函 数成员声明为基类的友元。 class b;/声明类声明类b class a int a,b; public: a(int x)a=x; friend b; /声明声明b为为a的友元类,的友元类,b类成员可以访问类成员可以访问a任何成员任何成员
15、; class b:a /缺省为缺省为private继承,等价于继承,等价于class b: private a int b; public: b(int x):a(x) b=x; a:b=x; /友元函数可访问私有成员友元函数可访问私有成员a:b ; void main(void) b x(7); 25 6.4 构造与析构构造与析构 v单继承派生类的构造和析构顺序比较容易确定: 调用虚基类的构造函数; 调用基类的构造函数; 按照派生类中数据成员的声明顺序,依次调用数据 成员的构造函数或初始化数据成员; 最后执行派生类的构造函数构造派生类。 v以下情况派生类必须定义自己的构造函数: f虚基类或
16、基类只定义了带参数的构造函数; f派生类自身定义了引用成员或只读成员; f派生类需要使用带参数构造函数初始化的对象成员。 26 6.4 构造与析构构造与析构 #include class a int a; public: a(int x):a(x)couta;/也可在构造函数体内用也可在构造函数体内用a=x再次初始化再次初始化 a( )couta; ; class b:a /私有继承,等价于私有继承,等价于class b: private a int b,c; const int d;/b中定义有只读成员,故必须定义构造函数初始化中定义有只读成员,故必须定义构造函数初始化 a x,y; pub
17、lic: b(int v):b(v),y(b+2),x(b+1),d(b),a(v)/注意构造与出现顺序无关注意构造与出现顺序无关 c=v; coutbcd; coutc; b( )coutd;/派生类成员实际构造顺序为派生类成员实际构造顺序为b,d,x,y ; void main(void) b z(1); /输出结果:输出结果:123111cd321 27 6.4 构造与析构构造与析构 v如果虚基类和基类的构造函数是无参的,则构 造派生类对象时,构造函数可以不用显式调用 它们的构造函数,编译程序会自动调用虚基类 或基类的无参构造函数。 v如果引用变量r引用的是一个对象v,则对象的 构造和析
18、构由对象v完成,而不应该由引用变量 r完成。如果被引用的对象是用new生成的,则 引用变量r必须用delete int *s; public: a(int x) s=new inti=x; cout(c): in; a( ) delete s; cout(d): in; ; void sub1(void) a void sub2(void) a *q=new a(2); void sub3(void) a delete void sub4(void) a *q=new a(4); delete q; void main(void) sub1( ); sub2( ); sub3( ); sub4
19、( ); 【例【例6.6】被引用的对象的析构】被引用的对象的析构。 输出:输出: (c): 1 (c): 2 (c): 3 (d): 3 (c): 4 (d): 4 29 6.5 父类和子类父类和子类 v如果派生类的派生控制为public,则这样的派生 类称为基类的子类子类,而相应的基类则称为派生 类的父类父类。 vc+允许父类指针直接指向子类对象,也允许父 类引用直接引用子类对象。 v通过父类指针调用虚函数时,根据对象的实际 类型绑定到合适的成员函数。父类指针实际指 向的对象的类型不同,虚函数绑定的函数的行 为就不同,从而产生多态。 30 6.5 父类和子类父类和子类 v编译程序只能根据类型
20、定义静态地检查语义。由 于父类指针可以直接指向子类对象,而到底是指 向父类对象还是子类对象只能在运行时确定。编 译时,只能把父类指针指向的对象都当作父类对 象。因此: f父类指针访问对象的数据成员或函数成员时,不能超 越父类为相应对象成员规定的访问权限; f也不能通过父类指针访问子类新增的成员,因为这些 成员在父类中不存在,编译程序无法识别。 31 6.5 父类和子类父类和子类 #include class point int x,y; public: int getx( ) return x; int gety( ) return y; void show( ) cout“show a po
21、intn”; point(int x,int y) point:x=x; point:y=y; ; class circle:public point/公有继承公有继承 int r; /私有成员私有成员 public: int getr( ) return r; void show( ) cout“show a circlen”; circle(int x,int y,int r):point(x,y) circle:r=r; ; 【例【例6.7】定义点类,并通过点类派生出圆类定义点类,并通过点类派生出圆类。 32 6.5 父类和子类父类和子类 void main(void) circle c
22、(3,7,8); point *p=/父类对象指针父类对象指针p指向子类对象,不用类型转换指向子类对象,不用类型转换 cout“the circle with radius ”getr( ),因为,因为getr( )函数不是父类的函数成员函数不是父类的函数成员 /编译程序无法通过检查编译程序无法通过检查 cout“ is at (”getx( )“,”gety( )show( ); /p虽然指向子类对象,但调用的是父类的虽然指向子类对象,但调用的是父类的show函数函数 输出结果:输出结果: the circle with radius 8 is at (3,7) show a point 3
23、3 6.5 父类和子类父类和子类 v若基类和派生类没有构成父子关系,则: f普通函数定义的基类指针不能直接指向派生类对象, 而必须通过强制类型转换才能指向派生类对象。 f普通函数定义的基类引用也不能直接引用派生类对 象,而必须通过强制类型转换才能引用派生类对象。 【例【例6.8】引用父类对象的引用变量引用子类对象引用父类对象的引用变量引用子类对象。 #include class a int a; public: int getv( ) return a; a( ) a=0; a(int x) a=x; a( ) coutan; ; class b: a/非父子:非父子:private int
24、b; public: int getv( ) return b+a:getv( ); b( ) b=0; b(int x):a(x) b=x; b( ) coutbn; ; 34 6.5 父类和子类父类和子类 class c: public a/父子关系父子关系 int c; /私有成员私有成员 public: int getv( ) return c+a:getv( ); c( ) c=0; c(int x):a(x) c=x; c( ) coutcn; ; void main(void) a /直接引用直接引用c类对象类对象 a /强制转换引用强制转换引用b类对象类对象 coutp.get
25、v( )=p.getv( )n; coutq.getv( )=q.getv( )n; delete /析构析构c(3)的父类的父类a而非子类而非子类c delete /析构析构b(5)的父类的父类a 而非子类而非子类b 输出:输出: p.getv( )=3 q.getv( )=5 a a 35 6.5 父类和子类父类和子类 v在派生类函数成员内部,定义的基类指针可以 直接指向该派生类对象,即对派生类函数成员 而言,基类被等同地当作父类。 v如果普通函数声明为基类的友元,则该普通函 数定义的基类指针也可以直接指向该基类的派 生类对象,也不必通过强制类型转换。 【例【例6.9】定义机车类】定义机车
26、类vehicle,并派生出汽车类,并派生出汽车类car。 class vehicle int speed,weight,wheels; public: vehicle(int spd,int wgt,int whl); friend void main( ); ; 36 6.5 父类和子类父类和子类 vehicle:vehicle(int spd, int wgt, int whl) speed=spd; weight=wgt; wheels=whl; class car: private vehicle/非父子关系非父子关系: private int seats; public: vehicle *who( ); car(in
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年度旅游合同担保期限与意外保险服务协议4篇
- 二零二五年度美容行业人才储备实习生就业合同4篇
- 二零二五版城市地下综合管廊建设及运营管理协议4篇
- 2025年度大型露天矿山资源承包开发合同4篇
- 2025年度重型车库门安全检测与维护服务合同4篇
- 二零二五年度大连业主支付担保办理及履约保障协议3篇
- 二零二五年度酒水节庆活动策划与执行服务合同2篇
- 2025版抹灰工程劳务分包施工安全保证合同4篇
- 二零二五年份土地经营权流转承包协议4篇
- 2025年度房地产项目场地使用权出让合同正规范本3篇
- 2024年人教版小学三年级信息技术(下册)期末试卷附答案
- 中国子宫内膜增生管理指南(2022)解读
- 应征公民政治考核表(含各种附表)
- 2024年第九届“鹏程杯”五年级语文邀请赛试卷
- 名师成长论名师成长的模式、机制和规律研究
- FSSC22000V6.0变化点和文件修改建议
- 2024年高一年级上册语文期末复习:语言文字运用Ⅰ刷题练习题(含答案)
- 新苏教版三年级下册科学全册知识点(背诵用)
- 乡镇风控维稳应急预案演练
- 脑梗死合并癫痫病人的护理查房
- 成都银行贷款合同
评论
0/150
提交评论