第6章 继承和派生类.ppt_第1页
第6章 继承和派生类.ppt_第2页
第6章 继承和派生类.ppt_第3页
第6章 继承和派生类.ppt_第4页
第6章 继承和派生类.ppt_第5页
已阅读5页,还剩31页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第二部分 C+面向对象程序设计,第六章 继承和派生类,本章内容, 继承性、基类和派生类的基本概念 派生类的定义和派生类对象的组成 派生类的构造函数和析构函数 虚基类 赋值兼容规则,6.1继承概述,类与类之间的关系,class B int a, b; public: B(int i, int j) a=i; b=j; ; class A int x; B bb; public: A( int i, int j, int k): bb (i, j), x( k ) ;,1、“有”关系(has a),#include class X friend class Y; int x; public: vo

2、id set(int i) x=i; void Display() coutx=xendl; ; class Y int yy; public: Y(int,X,2、“友”关系(friend),3、继承与派生 “是”关系(is a) 父子关系,继承的定义,继承:在原有类(基类或父类)的基础上,经过适当扩充和完善建立新的类(派生类或子类) 继承的本质是创建新的类新类不仅具有基类的特征,而且还可以添加新的特征,同时能够继续被继承而派生出新的类,继承的特点,扩充和完善原有程序以适应新的需求。 提高软件开发的效率,增加程序的重用性,减少代码和数据的冗余度。,讨论:is a 和has a的区别,三种继承

3、关系,6.2 基类和派生类,定义派生类的格式,class 派生类名: virtual 继承方式1 基类名1, virtual 继承方式2 基类名2, 派生类类体 ; 派生类类体中未定义的成员函数的实现,三种继承方式,public(公有继承) private(私有继承,缺省继承方式) protected(保护继承),回顾:成员的访问权限,class A public: int a; void f1(); private: int b; void f2(); protected: int c; void f3(); ;,A x;/x是什么? x.a=10;/是否可以? x.f1();/是否可以?

4、x.b=20;/是否可以? x.f2();/是否可以? x.c=30;/是否可以? x.f3();/是否可以? /成员函数定义 void A:f1() b=20; /是否可以?,如果不考虑继承,保护成员和私有成员的地位是一样的。 私有和保护成员只能被该类成员函数直接访问。 保护成员和私有成员的区别在于前者能被继承。,public公有继承方式,class A public: int a; void f1(); private: int b; void f2(); protected: int c; void f3(); ;,class B: public A int d; void f4();

5、public: int e; void f5(); ;,讨论: B有几个成员? 各是什么权限?,类B中: 公有成员: int a; void f1(); int e; void f5(); 保护成员: int c; void f3(); 私有成员: int b; void f2(); int d; void f4();,说明:在公有继承下,,直接基类的公有成员和保护成员分别作为派生类中的公有成员和保护成员。 直接基类的私有成员也会被继承,但派生类不能直接访问直接基类的私有成员。只能通过直接基类的公有成员函数和保护成员函数间接访问它们。 派生类的对象只能直接访问直接基类的公有成员。,void B

6、:f5() a=10; b=10; c=10; d=10; e=10; f2(); f3(); void A:f3() b=10; B x; x.a=100; x.e=200; x.f1();,private私有继承方式,class A public: int a; void f1(); private: int b; void f2(); protected: int c; void f3(); ;,class B: private A int d; void f4(); public: int f; void f5(); ;,直接基类的公有成员和保护成员均作为派生类的私有成员。,类B中:

7、公有成员: int f; void f5(); 私有成员: int a; void f1(); int c; void f3(); int b; void f2(); int d; void f4();,私有继承方式是默认的继承方式: class B:A ,protected保护继承方式,class A public: int a; void f1(); private: int b; void f2(); protected: int c; void f3(); ;,class B: protected A int d; void f4(); public: int f; void f5()

8、; ;,直接基类的公有成员和保护成员均作为派生类的保护成员。,类B中: 公有成员: int f; void f5(); 保护成员: int a; void f1(); int c; void f3(); 私有成员: int d; void f4(); int b; void f2();,不同继承方式下基类与派生类的特性,派生类对象的数据成员组成,例6.5 画出下面程序中类C对象obj1的组成结构图,class C :public B public: void f3(); protected: static int j3; void g3(); private: int i3; ; int C:

9、j3;,class A public: int k1; void f1(); protected: static int j1; void g1(); private: int i1; void h1(); ; int A:j1;,class B :public A public: void f2(); protected: int j2; void g2(); private: static int i2; A a1,a2; void h2(); ; int B:i2;,6.3 派生类的构造函数与析构函数,派生类构造函数的一般形式,派生类构造函数名(总参数表): 直接基类初始化表,子对象初始

10、化表, 派生类自身数据成员初始化表 派生类构造函数体 ,直接基类初始化表的形式为: 直接基类1构造函数 (参数表1), 直接基类2构造函数 (参数表2), 子对象初始化表形式为: 子对象名1(参数表1),子对象名2(参数表2), 派生类自身数据成员初始化表形式为: 数据成员名1(参数1),数据成员名2(参数2),class A int x; public: A() x=0; /缺省构造函数 A( int k) x=k; ;,class A int x; public: A() x=0; /数据成员初始化表 A( int k) : x(k) ;,class B int a, b; public:

11、 B() a=2; b=5; B(int i, int j) a=i; b=j; ; class A int x; B bb; public: A() x=0; /子对象初始化表 A( int i, int j, int k): bb (i, j), x( k ) ;,class B int a, b; public: B() a=2; b=5; B(int i, int j) a=i; b=j; ; class A : public B int x; B bb; public: A() x=0; /直接基类初始化表 A( int i1, int j1, int i, int j, int k

12、): B(i1, j1), bb (i, j), x( k ) ;,派生类构造函数的执行顺序,P173 例6.6 单重继承派生类构造函数示例,#include class Base public: Base() a=0; coutBase缺省构造函数n; Base(int i)a=i;coutBase构造函数n; void print()couta=a,; int Geta()return a; private: int a; ;,class Derived: public Base public: Derived()b=0; coutDerived缺省构造函数n; Derived (int

13、i, int j, int k): Base(i), Ba(j), b(k) cout“Derived 构造函数n”; void print() Base:print(); /调用基类Base的print()函数 coutb=b, Ba.a=Ba.Geta()endl; private: int b; Base Ba; /子对象或称为内嵌对象 ;,void main() Derived d1, d2(5,3,7); d1.print(); d2.print(); ,程序输出结果 : Base缺省构造函数 Base缺省构造函数 Derived缺省构造函数 Base构造函数 Base构造函数 De

14、rived构造函数 a=0,b=0,Ba.a=0 a=5,b=7,Ba.a=3,派生类析构函数,派生类析构函数的形式无特殊之处,不必显式地调用各直接基类各子对象相应类的析构函数,这些操作是由系统自动完成的 执行各析构函数的顺序恰好与执行各构造函数的顺序相反。,单重继承派生类析构函数示例,#include class Base public: Base() a=0; Base(int i) a=i; void print()couta=a,; int Geta()return a; Base()coutBase(a=a)析构函数n; private: int a; ;,class Derived

15、: public Base public: Derived()b=0; Derived(int i,int j,int k):Base(i),Ba(j)b=k; Derived() coutDerived(b=b)析构函数n; void print() Base:print(); coutb=b,Ba.a=Ba.Geta()endl; private: int b; Base Ba; ;,void main() Derived d1,d2(5, 3, 7); d1.print(); d2.print(); ,程序输出结果 : a=0,b=0,Ba.a=0 a=5,b=7,Ba.a=3 Deri

16、ved(b=7)析构函数 Base(a=3)析构函数 Base(a=5)析构函数 Derived(b=0)析构函数 Base(a=0)析构函数 Base(a=0)析构函数,例6.10 多重继承中构造函数和析构函数示例,#include class base1 int i1; public: base1(int i) i1=i; coutbase1(i1=i1)构造函数n; base1() coutbase1(i1=i1)析构函数n; ; class base2 int i2; public: base2(int i) i2=i; coutbase2(i2=i2)构造函数n; base2() c

17、outbase2(i2=i2)析构函数n; ;,class derived: public base1, public base2 base1 b1; base2 b2; int i3; public: derived(int j1, int j2, int j3, int j4, int j5) :base2(j2), base1(j1), b2(j3), b1(j4) i3=j5; coutderived构造函数n; derived() coutderived析构函数n; ; void main() derived d(5,4,3,2,1); ,程序输出结果 : base1(i1=5)构造

18、函数 base2(i2=4)构造函数 base1(i1=2)构造函数 base2(i2=3)构造函数 derived构造函数 derived析构函数 base2(i2=3)析构函数 base1(i1=2)析构函数 base2(i2=4)析构函数 base1(i1=5)析构函数,6.3.3虚基类,多重继承中的二义性问题,派生类对象通过不同继承路径而得到两个或两个以上同名成员 的问题。,struct A void f1() coutXixixin; ;,struct B void f1() cout“Hahahan; ;,struct C:public A, public B ;,声明:C x;

19、调用x.f1()会发生什么?,解决方法一:使用成员名限定来消除二义性。 如调用x.B:f1(); 方法二:成员函数重定义,struct C:public A, public B void f1() cout“Gegegen”; /B:f1(); ; /成员函数重定义,多级继承中的二义性问题,class A public: int na; void fun() coutfun() of A(na=na)n; ;,class B: public A public: int nb; ;,class C: public A public: int nc; ;,class D: public B, pu

20、blic C public: int nd; ;,void main() D d; d.B:na=2; d.C:na=3; coutd.B:A:na=d.B:na; coutnd.C:A:na=d.C:na; coutendl; d.B:fun(); d.C:fun(); ,程序输出结果 : d.B:A:na=2 d.C:A:na=3 fun() of A(na=2) fun() of A(na=3),虚基类:不希望结果具有二义性;希望只有一份间接基类的成员被继承下来 。则可以把间接基类转为虚基类,void main() D d; d.na=3; coutd.nad.naendl; d.fun

21、(); ,程序输出结果 : d.na=3 fun() of A(na=3),虚基类的构造函数和析构函数,虚基类的数据成员只被初始化一次 。 在一个基类初始化表中,若同时出现对虚基类和非虚基类构造函数的调用,则虚基类的构造函数优先执行。若同时包括多个虚基类,则按它们在定义派生类时说明的顺序调用各虚基类的构造函数。 p248例8.11 虚基类构造、析构函数调用示例,class A public: A() coutA classn; A()coutclass An; ;,class D1 public: D1() cout“D1 classn; D1()coutclass D1n; ;,class

22、D2: public D1, virtual public A public: D2() cout“D2 classn; D2()coutclass D2n; ;,class D3: public D1, virtual public A public: D3() cout“D3 classn; D3()coutclass D3n; ;,class D4: public D2, virtual public D3 public: D4() cout“D4classn; D4()coutclass D4n; ;,void main() D4 d; ,程序输出结果 : A class D1 cla

23、ss D3 class D1 class D2 class D4 class class D4 class D2 class D1 class D3 class D1 class A,6.4 赋值兼容规则,class A int m, n; ; class B ; main() A x; B y; /什么情况下可以? x=y; ,不同类型的对象之间的转换,结论: 1、B必需是A的派生类。 2、B对A必需是公有继承的,赋值兼容规则,赋值兼容规则 赋值兼容规则:是指在公有继承的前提下,基类对象与公有派生类对象之间的自动类型转换和赋值的规则。 规则只对公有继承有效。如果对私有继承或保护继承使用,则会

24、出现语法错误。 由于派生类中包含从基类继承的成员,所以可以将派生类对象赋值给基类对象,在需要基类对象的任何时候都可以其用派生类对象代替。 赋值兼容规则主要包括两个内容:基类对象与派生类对象之间的关系;基类对象的指针与派生类对象的指针之间的关系。,基类对象与派生类对象之间的关系,可以用派生类对象给基类对象赋值,反之不行 。 可以用派生类对象初始化基类对象或基类的引用。 如果函数的形参是基类对象或基类对象的引用,则对应的实参可以是派生类的对象。 可以把派生类对象的地址赋给指向其基类对象的指针变量。反之不行。 可以把派生类对象的指针赋值给基类对象的指针。反之则错。,base b; derived d

25、; b=d; d=b; /错,derived d; base b(d); base ,base b, *pb; derived d, *pd; pb= /错,base *pb; derived d, *pd= /错,#include class A int x; public: A(int x1)x=x1; void print() coutx=x ; ; class B: public A int y; public: B(int x1,int y1):A(x1)y=y1; void print() A:print(); couty=yendl; ;,void main() B b1(10,20); b1.print(); A a(b1); a

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论