版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第七章 继承和派生一、 基类和派生类1. 在C+中,可以从一个类派生出另一个类,前者称为基类或父类,后者称为派生类或子类。一个派生类可以从一个或多个基类派生。从一个基类派生的继承称单继承,从多个基类派生的继承称多继承。2. 单继承定义格式: class 派生类:继承方式 基类 派生类新定义成员; ; 其中,“派生类”是从“基类”按指定的“继承关系”派生出的、新定义的一个类的名字。“继承方式”有三种:(1)public 公有继承 (2)private 私有继承 (3) protected 保护继承3. 多继承定义格式: class 派生类:继承方式1 基类1,继承方式2 基类2, 派生类新定义成
2、员; ;4. 公有继承:当派生类的继承方式是public继承时,基类的public和protected成员的访问属性在派生类中保持不变,而基类的private成员不可访问,即基类的public和protected成员分别作为派生类的public和protected成员,派生类的其他成员可以直接访问它们。 例1: class B private: int x; protected: int y; public: int z; ; class A:public B private: int a; protected: int b; public: int c; A a; (1) 类B是基类,有3个
3、数据成员x、y、z,分别是private、protected、public属性。类A是派生类,有3个数据成员a、b、c,分别是private、protected、public属性。由于类A是从类B公有派生的,类B中的public、protected属性的成员可继承到类A中来,且保持原来的属性。故类A中有5个数据成员,即a、b、c、y。(2) 可以通过类A的对象a直接访问public成员,即z和c,并不能访问a、b、y数据成员。 (3) 不考虑派生类时,类中的private和protected属性的成员都可以被类的成员函数访问,而都不能被该类的对象直接访问。在派生类中,当公有继承时,基类中pro
4、tected属性的成员可以作为派生类的protected属性的成员,而private属性的成员不能作为派生类的成员。5. 保护继承:当派生类的继承方式是protected继承时,基类的public和protected成员可以被继承到派生类中,但访问属性都变成protected,而基类的private成员不可访问,即基类的public和protected成员都作为派生类的protected成员,派生类的其他成员可以直接访问它们。例2: class B private: int x; protected: int y; public: int z; ; class A:protected B pr
5、ivate: int a; protected: int b; public: int c; A a;类B是基类,有3个数据成员x、y、z,分别是private、protected、public属性。类A是从类B保护派生的,类B中的protected、public属性的成员可继承到类A中,均变成protected属性。故类A中有5个数据成员,即a、b、c、y、z。可以通过类A的对象a直接访问public成员,即c,不能访问a、b、y、z数据成员。6. 私有继承:当派生类的继承方式是private继承时,基类的public和protected成员可以被继承到派生类中,但访问属性都变成privat
6、e,而基类的private成员不可访问,即基类的public和protected成员都作为派生类的private成员,派生类的其他成员可以直接访问它们。例3: class B private: int x; protected: int y; public: int z; ; class A:private B private: int a; protected: int b; public: int c; A a;类B是基类,有3个数据成员x、y、z,分别是private、protected、public属性。类A是从类B私有派生的,类B中的protected、public属性的成员可继承到
7、类A中,均变成private属性。故类A中有5个数据成员,即a、b、c、y、z。可以通过类A的对象a直接访问public成员,即c,不能访问a、b、y、z数据成员。二、 单继承1. 在单继承中,每个类可以有多个派生类,但是每个派生类只能有一个基类,从而形成树形结构。2. 构造函数不能被继承,故派生类的构造函数必须通过调用基类的构造函数来初始化基类子对象。在定义派生类的构造函数时,除了要对自己的数据成员进行初始化,还要调用基类构造函数使基类的数据成员得以初始化。若派生类中还有子对象,应包含对子对象初始化的构造函数。3. 派生类构造函数一般格式: 派生类名(派生类构造函数总参数表):基类构造函数(
8、参数表1), 子对象名(参数表2) 派生类中数据成员初始化; ;4. 派生类构造函数调用顺序:(1)基类的构造函数;(2)子对象类的构造函数(有的话);(3)派生类构造函数。例4: class A public: A() cout”A Constructor”endl; ; class B:public A public: B() cout”B Constructor”endl; ; void main() B b; 执行结果为: A Constructor B Constructor5. 当对象被删除时,派生类的析构函数被执行。析构函数也不能被继承,故在执行派生类的析构函数时,基类的析构函数
9、也将被调用。析构函数的执行顺序是先执行派生类的析构函数,再执行基类的析构函数。例5: class A public: A() cout”A Constructor”endl; A() cout”A Destructor”endl; ; class B:public A public: B() cout”B Constructor”endl; B() cout”B Destructor”endl; ; void main() B b; 执行结果为: A Constructor B Constructor B Destructor A Destructor6. 派生类构造函数的定义中可以省略对基类
10、构造函数的调用,条件是在基类中必须有默认的构造函数或根本没有定义构造函数。7. 当基类的构造函数使用一个或多个参数时,则派生类必须定义构造函数,提供将参数传递给基类构造函数的途径。有的情况下,派生类构造函数的函数体可能为空,仅起到参数传递的作用。三、 多继承1. 多继承是指派生类具有多个基类,派生类和每个基类间的关系仍可看作一个单继承。 如: class A ; class B; class C:public A,public B ; 其中派生类C具有两个基类,故为多继承。派生类C的成员包含了基类A和基类B中的成员和它本身的成员。2. 多继承派生类的构造函数格式: 派生类名(总参数表):基类名
11、1(参数表1),基类名2(参数表2), 基类名n(参数表n),子对象名(参数表n+1) 派生类构造函数体; 其中,“总参数表”中各个参数包含了其后的各个分参数表。3. 多继承和单继承派生类的构造函数必须同时负责该派生类所有基类构造函数的调用,且派生类的参数个数必须包含完成所有基类初始化所需的参数个数。4. 多继承派生类构造函数的执行顺序:(1)调用基类的构造函数,调用次序按照它们被继承时说明的次序(从左到右)。(2)调用子对象的构造函数,调用次序按照它们在类中说明的次序。(3)调用派生类的构造函数。5. 对于处于同一层次的各基类构造函数的执行顺序取决于定义派生类时所指定的各基类顺序,与派生类构
12、造函数中所定义的成员初始化列表中的各项顺序无关。 例6: class A int a; public: A(int i) a=i; cout”A Constructor”endl; void disp() cout”a=”aendl; ; class B int b; public: B(int j) b=j; cout”B Constructor”endl; void disp() cout”b=”bendl; ; class C:public B,public A int c; public: c(int k):A(k-2):B(k+2) c=k; cout”C Constructor”e
13、ndl; void disp() A:disp(); B:disp(); cout”c=”cendl; ; void main() C obj(10); obj.disp(); 执行结果为:B Constructor A Constructor C Constructor a=8 b=12 c=106. 多继承中析构函数的执行顺序与构造函数的顺序正好相反。7. 在派生类中对基类成员的访问应该是唯一的,但在多继承下,可能造成对基类中某个成员的访问出现了不唯一的情况,称为对基类成员访问的二义性问题。一般解决方法是采用作用域运算符:。四、 虚基类1. 虚基类说明格式: virtual 继承方式 基类
14、 其中,virtual是虚基类的关键字。虚基类的说明用在定义派生类时,写在派生类名后面。例7: class x protected: int a; public: x() a=10; ; class x1:public x public: x1() coutaendl; ;class x2:public x public: x2()coutaendl; ;class y:x1,x2 public: y() coutaendl; /二义性,是x1:a还是x2:a ;void main() y obj; 此时,通过引入虚基类消除二义性。引入虚基类后,派生类的对象中只存在一个虚基类的子对象。当一个类
15、有虚基类时,编译系统将为该类的对象定义一个指针成员,让它指向虚基类的子对象。该指针叫虚基类指针。上面程序应改为: class x1:virtual public x public: x1() coutaendl; ;class x2:virtual public x public: x2()coutaendl; ;2. 虚基类的初始化和多继承类的语法一样,但调用派生类构造函数的顺序应遵守以下原则: (1)虚基类的构造函数在非虚基类前调用。(2)若同一层次中包含多个虚基类,则虚基类的构造函数按它们说明的顺序调用。(3)若虚基类由非虚基类派生而来,则仍先调用基类构造函数,再调用派生类中构造函数的执
16、行顺序。例7: class base1 public: base1() cout”class base1”endl; ; class base2 public: base2() cout”class base2”endl; ; class level1:public base2,virtual public base1public: level1() cout”class level1”endl; ; class level2:public base2,virtual public base1public: level2() cout”class level2”endl; ; class to
17、plevel:public level1,virtual public level2public: toplevel () cout”class toplevel”endl; ; void main() toplevel obj; 整个obj对象的各构造函数的执行顺序为: base1()、base2()、level2()、base2()、level1()、toplevel(). 执行结果为: class base1 class base2 class level2 class base2 class level1 class toplevel 3. 一般,当定义虚基类的构造函数时,虚基类只允许
18、定义不带参数的或带默认参数的构造函数。五、 模板和继承1. 类模板可以从类模板中派生,此时两个类模板的类型参数有关联关系。在定义派生类时必须指定这个类模板的类型参数。例8: template class A public: void dispa(T obj) coutobjendl; ; template class B:public A public:void dispb(T1 obj1,T2 obj2) coutobj1”obj2endl; ; void main() B obj1; obj1.dispa(12.34); obj1.dispb(“The value is:”56.78);
19、B obj2; obj2.dispb(89,10); B obj3; obj3.disp(2.3,”is OK.”); B obj4; obj4.dispb(I,”and you”); 执行结果: 12.34 The value is:56.78 89 10 2.3 is OK. I and you2. 类模板可以从非类模板中派生,此时模板继承非模板的成员,再从类模板实例化模板类,最后从该模板类实例化成对象。 例9: class A int x; public: A(int i) x=i; int getx() return x; void disp() coutxendl; ; templa
20、te class B:public A T y; public: B(T a,int j):A(j) y=a; T gety() return y; void disp() couty”getx()endl; ;void main() A obj(123); obj.disp(); B obj1(1,2); B obj2(1.3,5); B obj3(“It is”,10); B obj4(=,20);obj1.disp(); obj2.disp(); obj3.disp(); obj4.disp(); 执行结果: 123 1 2 1.3 5 It is 10 =203. 非类模板可以从类模板
21、中派生,此时必须在非模板类中指定基模板类(即将类模板实例化成模板类),再从该非模板类实例化成对象。例10: class A protected: T x; public: A(T i) x=i; ;class B:public A int y; public: B(int i,int j):A(i) y=j; void disp() cout”x=”x”,y=”yendl; ; void main() B obj(1,2); obj.disp(); 执行结果: x=1,y=2习题 1. C+中的类有两种用法:一种是类的实例化,即生成类的对象,并参与系统的运行;另一种是通过( )派生出新的类。
22、2. 继承具有( )性,即当基类本身也是某一个类的派生类时,底层的派生类也会自动继承间接基类的成员。 3. 在多继承中,公有派生和私有派生对于基类成员在派生类中的可访问性与单继承的规则( )。 4. 派生可分为( )和( )。由( )得到得派生类,其基类的所有公有成员都只能成为它的私有成员,这些私有成员只能被派生类的成员函数访问,而通过( )无权访问它;( )的意义是基类中所有公有成员在派生类中也都是公有的。 5. 基类的( )不能为派生类的成员访问,基类的( )在派生类中的性质和继承的性质一样,而基类的( )在私有继承时在派生类中成为私有成员,在公有和保护继承时在派生类中仍为保护对象。 6.
23、 ( )提供了类对外部的界面,( )只能被类的成员访问,而( )不允许外界访问,但允许派生类的成员访问,这样既有一定的隐藏能力,又提供了开放的界面。 7. 若类A和类B定义如下:( )是非法的表达式。 class A int I,j; public: void get(); / ; class B:A int k; public: void make(); / ; void B:make() k=i*j; 8. 派生类的对象对它的基类成员中( )继承的( )成员是可以访问的。 9. 设置虚基类的目的是( )。 10. 对于派生类的构造函数,在定义对象时构造函数的执行顺序为:先执行( ),再执行
24、( ),后执行( )。 11. 下面说法错误的是( )。 A. 一个派生类可以作为另一个派生类的基类 B. 派生类至少有一个基类 C. 派生类的成员除了它自己的成员外,还包含了它的基类的成员 D. 派生类中继承的基类成员的访问权限到派生类保持不变 12. 下面描述错误的是( )。 A. 派生类是基类的具体化 B. 派生类是基类的子集 C. 派生类是基类定义的延续 D. 派生类是基类的组合 13. 派生类的构造函数的成员初始化列表中,不能包含( )。 A. 基类的构造函数 B. 派生类中子对象的初始化 C. 基类的子对象初始化 D. 派生类中一般数据成员的初始化 14. 关于多继承二义性的描述,
25、错误的是( )。 A. 一个派生类的两个基类中都有某个同名成员,在派生类中对这个成员的访问可能出 现二义性 B. 解决二义性的做常用方法是对成员名的限定 C. 基类和派生类中出现同名函数,也存在二义性问题 D. 一个派生类是从两个基类派生来的,而这两个基类又有一个共同的基类,对该基类成员进行访问时,也可能出现二义性 15. 以下程序的执行结果为( )。 class A public: A(int i,int j) a=i; b=j; void move() int x,int y a+=x; b+=y; void show() cout”(”a”,”b”)”endl; private: int
26、 a,b; ; class B:public A public: B(int i,int j,int k,int l):A(i,j),x(k),y(l) void show() coutx”,”yendl; void fun()move(3,5); void f1() A:show(); private: int x,y; ; void main() A e(1,2); e.show(); B d(3,4,5,6); d.fun(); d.A:show(); d.B:show(); d.f1(); 16. 阅读程序回答问题。class A public: void f1(); A() i1=1
27、0; j1=11; protected: int j1; private: int i1; ; class B:protected A public: void f2(); B() i2=20; j2=21; protected: int j2; private: int i2; ;class C:protected B public: void f3(); c() i3=30;j3=31; protected: int j3; private: int i3; ;(1) 派生类B中成员函数f2()能否访问基类A中的成员f1()、i1和j1?(2) 派生类B的对象b能否访问基类A中的成员f1()、i1、j1?(3) 派生类C中成员函数f3()能否访问直接基类B中得成员f2()和j2?能否访问间接基类A中的成员
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年安庆医药高等专科学校单招综合素质考试题库及答案1套
- 2026年涉外会议保密员技能提升试题及完整答案1套
- 2026年新疆科技职业技术学院单招职业技能测试模拟测试卷及答案1套
- 2026年江西省抚州市单招职业倾向性测试模拟测试卷附答案
- 2026年心理账户期末测试题及参考答案
- 2026年广东松山职业技术学院单招职业技能考试模拟测试卷及答案1套
- 2026年山西铁道单招试题附答案
- 2026上海浦东新区妇女联合会文员公开招聘2人笔试备考题库及答案解析
- 2026四川自贡医元健康管理有限责任公司招聘工作人员11人笔试备考题库及答案解析
- 2026贵州安顺长水实验学校招聘24人笔试备考题库及答案解析
- 6.1.3化学反应速率与反应限度(第3课时 化学反应的限度) 课件 高中化学新苏教版必修第二册(2022-2023学年)
- 北京市西城区第8中学2026届生物高二上期末学业质量监测模拟试题含解析
- 2026年辽宁轻工职业学院单招综合素质考试参考题库带答案解析
- 2026届北京市清华大学附中数学高二上期末调研模拟试题含解析
- 2026年马年德育实践作业(图文版)
- 医院实习生安全培训课课件
- 四川省成都市武侯区西川中学2024-2025学年八上期末数学试卷(解析版)
- 2026年《必背60题》抖音本地生活BD经理高频面试题包含详细解答
- 土方回填工程质量控制施工方案
- 2025年湖南城建职业技术学院单招职业适应性测试题库附答案
- 2026贵州大数据产业集团有限公司第一次社会招聘考试题库新版
评论
0/150
提交评论