版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第12章派生C+类,多态性:应用一条指令,完成多个任务。 继承性通过派生类实现,多态性通过虚函数实现。,面向对象程序设计的重要特性: 继承性 多态性,继承性:继承是软件复用的一种形式,其实现方法是从现有的类建立新类。使得新类可以复用已有类的代码,引用其属性,并对其进行覆盖和改写,产生新类所需要的功能,节省软件开发时间。,派生类的定义,class S1: public S /以public方式声明派生类S1 public: void set_value( ) cinageaddr; void display( ) cout age: ageendl; /引用派生类的私有成员 cout addr:
2、 addrendl; /引用派生类的私有成员 private: int age; char addr40; ;,class 派生类名:继承方法 基类名 派生类新增的成员及成员函数,继承方式有: public private protected (公用的)(私有的)(受保护的) 不同继承方式的影响主要体现在: 派生类成员对基类成员的访问权限,S 基类 父类 S1 派生类 子类,二. 派生类的构造函数 1、派生类构造函数 派生类构造函数名(基类所需的形参,本类成员所需的形参):基类构造函数名(参数列表) 派生类新增成员的初始化语句,S(n,nam,s)为基类的构造函数,用来初始化基类的数据成员,类
3、S1是用成员函数void set_value( )设置数据成员。可用下面构造函数初始化数据成员。 S1(int n, char nam , char s, int a, char ad ):S(n,nam,s) age=a; strcpy(addr,ad); ,2、私有继承:private class S1 : private S 则: 基类中的所有公有成员为派生类的私有成员, 基类中的所有保护成员为派生类的私有成员 (都不能被这个派生类的子类所访问) 基类中的私有成员在派生类中不可访问,三、派生特性 1、公有继承: class S1: public S 则: 基类中的公有成员在派生类中也是公
4、有成员。 基类中的保护成员在派生类中也是保护成员。 基类中的私有成员在派生类中不可访问,只有基类的成员函数可以引用它,不能被派生类的成员函数引用,在派生类中不可访问,3、保护继承:protected class S1: protected S 则: 基类中的公有成员在派生类中也是保护成员。 基类中的保护成员在派生类中也是保护成员。 (只能被它的派生类成员函数或友元访问) 基类中的私有成员在派生类中不可访问,公有派生类用的最多,其它两种很少用。 如果不指定public或private,则类缺省采用私有派生。,派生特性,12.2 生成类的层次结构,派生类又可做为另一派生类的基础类,生成相关类的层次
5、结构。 一 .单继承 每个类可以有多个派生类,但是每个派生类只能有一个基类,从而形成树形结构。,class B:protected A public: void pub2(); protected: int pro2; private: int pri2; ;,class C:public B public: void pub3(); ;,class D:private C public: void pub4(); ;,pub1() pro1 pri1 pub2() pro2 pri2 pub3() pub4(),回答p148页的问题,例: 12.10 #include class A pub
6、lic: void pub1(); protected: int pro1; private: int pri1; ;,基类 A 公用 保护 私有,保护派生类B 保护 保护 不可访问 公用 保护 私有,公用派生类C 保护 保护 不可访问 公用 保护 不可访问 公用,私有派生类D 私有 私有 不可访问 私有 私有 不可访问 私有 公用,派生类B中成员函数pub2()能访问基类A中的哪些成员?,在main函数中能否用派生类B的对象b1访问基类A中成员pub1()、pro1和pri1?,派生类C中成员函数pub3()能访问直接基类B中的哪些成员?能访问间接基类A中的哪些成员?,在main()函数中能
7、用派生类C的对象c1访问直接基类B中的哪些成员?能访问间接基类A中的哪些成员?,派生类D的成员函数pub4()能访问直接基类C中的哪些成员?能访问间接基类B、A中的哪些成员?,在main()函数中能否用派生类D的对象d1访问直接基类C中的哪些成员?能访问间接基类B、A中的哪些成员?,二类型适应 如果由类A派生类B,则B类型适应A类型。即B类型对象适用于A类型对象作用的场合。,#include class A public: A()a=0; A(int i)a=i; void print() coutaAs printendl; private: int a; ;,class B:public
8、A public: B()b=0; B(int i,int j):A(i),b(j) void print()coutb”Bs printendl; private: int b; ;,void main() B bb(9,10); A aa(5); aa=bb; aa.print(); bb.print(); B *pb= ,尽管基类指针、基类引用指向了派生类对象,但在调用print()时,仍然调用基类中的print()。,二类型适应 如果由类A派生类B,则B类型适应A类型。即B类型对象适用于A类型对象作用的场合。 类型兼容规则,一个公有派生类的对象在使用上可以被当作基类的对象,反之则禁止。
9、具体表现在: 派生类的对象可以被赋值给基类对象。 派生类的对象可以初始化基类的引用。 指向基类的指针也可以指向派生类。 通过基类对象名、指针只能使用从基类继承的成员,class 派生类名:继承方式1 基类名1,继承方式2 基类名2,. 成员声明; 注意:每一个“继承方式”,只用于限制对紧随其后之基类的继承。,三、多继承时派生类的声明,基类的构造函数不被继承,派生类中需要声明自己的构造函数。 声明构造函数时,只需要对本类中新增成员进行初始化,对继承来的基类成员的初始化,自动调用基类构造函数完成。 派生类的构造函数需要给基类的构造函数传递参数,1、多继承时的构造函数,派生类名:派生类名(基类1形参
10、,基类2形参,.基类n形参,本类形参):基类名1(参数), 基类名2(参数), .基类名n(参数) 本类成员初始化赋值语句;,派生类名:派生类名(基类1形参,基类2形参,.基类n形参,本类形参):基类名1(参数), 基类名2(参数), .基类名n(参数),对象数据成员的初始化 本类成员初始化赋值语句;,多继承且有内嵌对象时的构造函数,多继承时的构造函数,四多继承举例 1多继承:派生类有多个基类。 class A :; class B :; class C: public A,public B :; 2.多继承的构造函数: 执行基类构造函数的顺序取决于定义派生类时基类的顺序。 对象成员的构造函数
11、的调用顺序取决于对象成员在类中定义的顺序。,class A public: void setA(int); void showA(); private: int a; ; class B public: void setB(int); void showB(); private: int b; ; class C : public A, private B public: void setC(int, int, int); void showC(); private: int c; ;,void main() C obj; obj.setA(5); obj.showA(); obj.setC(
12、6,7,9); obj.showC(); ,void A:setA(int x) a=x; void B:setB(int x) b=x; void C:setC(int x, int y, int z) /派生类成员直接访问基类的 /公有成员 setA(x); setB(y); c=z; /其它函数实现略,/ obj.setB(6); / obj.showB();,#include“iostream.h” 例12.14 class M1 public: M1(int i) m1=i; coutconstruM1.iendl; void print() coutm1endl; M1()cout
13、destruM1.endl; private: int m1; class M2 public: M2(int i) m2=i; coutconstruM2.iendl; void print() coutm2endl; M2()coutdestruM2.endl; private: int m2; ;,class N: public M2,public M1 public: N(int i,int j,int k,int l):M1(i),M2(j),mm1(k),mm2(l) n=3;coutconstructor N.lendl; void print() M1:print();M2:p
14、rint();coutnendl; N()coutdestructor N.endl; private: int n; M1 mm1; M2 mm2; ; void main() N nn(1,2,3,4); nn.print(); ,class C: public B2, public B1, public B3 public: C(int a, int b, int c, int d): B1(a),memberB2(d),memberB1(c),B2(b) private: B1 memberB1; B2 memberB2; B3 memberB3; ; void main() C ob
15、j(1,2,3,4); ,例: 派生类析构函数举例 #include class B1/基类B1声明 public: B1(int i) coutconstructing B1 iendl; B1() coutdestructing B1 endl; ; class B2/基类B2声明 public: B2(int j) coutconstructing B2 jendl; B2() coutdestructing B2 endl; ; class B3/基类B3声明 public: B3()coutconstructing B3 *endl; B3() coutdestructing B3
16、endl; ;,constructing B2 2 constructing B1 1 constructing B3 * constructing B1 3 constructing B2 4 constructing B3 * destructing B3 destructing B2 destructing B1 destructing B3 destructing B1 destructing B2,3二义性问题 在派生类中对基类成员的访问应该是惟一的。但是,在多继承的情况下,派生类有多个基类,如果这些基类中有相同名字的成员,在派生类中对这些成员访问时,有可能出现二义性。带有二义性的访
17、问是错误的,应消除。,例: class A public: void f() ; class B public: void f();void g(); class C :public A,public B public : void g( );void h();,设定义:C C1; C1.f()具有二义性,是A中的f()还是B中的f()? c1.g()无二义性,属于同名覆盖,解决办法由二: 1.可以用作用域操作符: C1.A:f(); C1.B:f(); 2. 同名覆盖 在C 中声明一个同名成员函数f(),f()再根据需要调用 A:f() 或 B:f(),class C : public B1
18、,public B2 public: int f(); private: int d; ,例 class B public: int b; class B1 : public B private: int b1; class B2 : public B private: int b2; ;,有二义性吗: C c; c.b c.B:b,有二义性吗: c.B1:b c.B2:b,四虚基类 虚基类的引入和说明 用于有共同基类的场合,引入虚基类的真正目的是为了解决二义性问题。 说明 以virtual修饰说明基类例:class B1:virtual public B class B2:virtual p
19、ublic B,注意: 在第一级继承时就要将共同基类设计为虚基类。,2. 作用: 多继承的情况下,如果派生类的多个直接基类是由一个间接基类派生而成,则在派生类中访问间接基类的成员时,会出现二义性问题。 为最远的派生类提供唯一的基类成员,而不重复产生多次拷贝。,class A public: void f( ) ; protected: int a; ; class B: virtual public A protected: int b; ; class C: virtual public A protected: int c; class D: public B,public C publi
20、c: int g( ) private: int d; ;,下面的引用正确 D n; n.f( ) void D:g( ) f ( ); 若不定义成虚基类 则n.f( ); 具有二义性 定义成虚基类后只有一个消除了二义性,虚基类,在声明派生类时,将关键词virtual加到相应的继承方式前面,说明成虚基类后,当基类通过多条路径被一个派生类继承时,该派生类只继承该基类一次。 基类成员只保留一次。,虚基类的初始化,如果在虚基类中定义了带参数的构造函数,而且没有定义默认构造函数,则在其所有派生类(包括直接派生或间接派生的派生类)中,必须通过构造函数的初始化表对虚基类进行初始化。,class A /定义
21、基类A A(int i) /基类构造函数,有一个参数 ;,class B:virtual public A /A作为B的虚基类 B(int n):A(n) /B类构造函数,在初始化表中对虚基类初始化 ;,class C:virtual public A /A作为C的虚基类 C(int n):A(n) /C类构造函数,在初始化表中对虚基类初始化 ;,class D: public B, public C D(int n):A(n),B(n),C(n) /D类构造函数,在初始化表中对所有基类初始化 ;,规定:在最后的派生类中不仅要负责对其直接基类进行初始化,还要负责对虚基类初始化。,由于虚基类在派
22、生类中只有一份数据成员,所以这份数据成员的初始化必须由派生类直接给出。如果不由最后的派生类(类D)直接对虚基类初始化,而由虚基类的直接派生类(类B和类C)对虚基类初始化,就有可能由于在类B和类C的构造函数中对虚基类给出不同的初始化参数而产生矛盾。,问题:类D的构造函数通过初始化表调用了虚基类的构造函数A,而类B和类C的构造函数也通过初始化表调用了虚基类的构造函数A,这样虚基类的构造函数岂非被调用了3次? 不是! C+编译系统执行最后的派生类对虚基类的构造函数的调用,而忽略虚基类的其他派生类对虚基类的构造函数的调用。,#include class B0 public: B0(int n) nV=
23、n; int nV; void fun()coutnV tMember of B0endl; ; class B1: virtual public B0 public: B1(int a) : B0(a) int nV1; ; class B2: virtual public B0 public: B2(int a) : B0(a) int nV2; ;,class D1: public B1, public B2 public: D1(int a) : B0(a), B1(a), B2(a) int nVd; void fund()coutMember of D1endl; ; void m
24、ain() D1 d1(1); d1.nV=5; d1.fun(); ,coutnV tMember of B0endl;,2虚基类的构造函数 注:虚基类构造函数只能被调用一次。(因只有一个虚基类) 由于继承的层次很深,规定将在建立对象时所指定的类称为最派生类。 如果派生类有一个直接或间接的虚基类,那么派生类的构造函数和成员初始化列表中必须列出对虚基类函数的调用。若无列出,调用缺省虚基类构造函数。 从虚基类直接或间接继承的派生类中的构造函数和成员初始化列表中都要列出这个虚基类构造函数的调用。但是,由用于建立对象的那个最派生类的构造函数调用虚基类的构造函数。 C+规定,在成员初始化列表中出现对虚
25、基类和非虚基类构造函数的调用,则虚基类的构造函数先于非虚基类的构造函数的执行。 P157 12.15,#include iostream.h class A public: A(int i) a=i;coutcon.An; void print1() coutvirtual classendl; void print2() coutaendl; A()coutdes.An; private: int a; ; class B1:virtual public A public: B1(int i,int j): A(i) b1=j;coutcon.B1n; void print() coutb1endl; B1()coutdes.B1n; private: int b1; ;,class B2:virtual public A public: B2(int i,int j): A(i) b2=j;coutcon.B2n; void print()coutb2endl; B2()coutdes.B2n; p
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026中国消费电子行业市场格局与品牌竞争分析报告
- 2026中国通信设备行业市场供需分析及投资机会评估规划分析研究报告
- 2026中国特医食品注册审批与临床需求匹配度分析报告
- 2026中国智能汽车维修行业市场供需分析及投资评估规划分析研究报告
- 2026年鸡西市恒山区街道办人员招聘考试备考试题及答案详解
- 2026年南通市港闸区法检系统书记员招聘考试参考试题及答案详解
- 2026年陕西省宝鸡市街道办人员招聘笔试参考题库及答案详解
- 2026年张家口市宣化区街道办人员招聘考试参考试题及答案详解
- 2026年牡丹江市阳明区中小学教师招聘考试参考题库及答案详解
- 2026年鹤壁市山城区中小学教师招聘笔试备考试题及答案详解
- 2025工贸企业董事长安全生产责任制培训
- 火力发电厂典型事故案例汇编
- 保证药品信息来源合法、真实、安全的管理措施、情况说明及相关证明资料
- 2026年湖南事业单位招聘(公基)笔试真题及答案
- 关键岗位考核制度细则
- 人工智能在医疗设备故障诊断中的应用
- 福建省厅警用地理信息系统(PGIS2.0)建设方案V1.1
- 华为公司质量管理
- 2025四川遂宁发展投资集团有限公司招聘8人笔试参考题库附答案
- (正式版)DB44∕T 2713-2025 《陆生野生动物样品采集和保存技术规范》
- 主网线路专业知识培训课件
评论
0/150
提交评论