C++面向对象程序设计第5章教程_第1页
C++面向对象程序设计第5章教程_第2页
C++面向对象程序设计第5章教程_第3页
C++面向对象程序设计第5章教程_第4页
C++面向对象程序设计第5章教程_第5页
已阅读5页,还剩51页未读 继续免费阅读

下载本文档

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

文档简介

1、1第五章 继承和派生类2继承性是面向对象程序设计中最重要的机制。这种继承性是面向对象程序设计中最重要的机制。这种机制机制提供了无限重复利用程序资源的一种途径提供了无限重复利用程序资源的一种途径。通过通过C+语言中的继承机制,语言中的继承机制,可以扩充和完善旧的可以扩充和完善旧的程序设计以适应新的需求。程序设计以适应新的需求。这样不仅可以节省程序开发的时间和资源,并且为这样不仅可以节省程序开发的时间和资源,并且为未来程序增添了新的资源。未来程序增添了新的资源。5.1 派生和继承的相关概念和作用派生和继承的相关概念和作用3class Student int num; char name30; ch

2、ar sex; public: void display( ) /对成员函数对成员函数display的定义的定义 coutnum: numendl; coutname: nameendl; coutsex: sexendl; ;5.1 派生和继承的相关概念和作用派生和继承的相关概念和作用4class Studend1 int num; /此行原来己有此行原来己有 char name20; /此行原来己有此行原来己有 char sex; /此行原来己有此行原来己有 int age; char addr20; public: void display( ) ; /此行原来己有此行原来己有 cout

3、num: numendl; /此行原来己有此行原来己有 coutname: nameendl;/此行原来己有此行原来己有 coutsex: sexendl; /此行原来己有此行原来己有 coutage: ageendl; coutaddress: addrendl; ; 5.1 派生和继承的相关概念和作用派生和继承的相关概念和作用5利用原来定义的类利用原来定义的类StudentStudent作为基础,再加上新的作为基础,再加上新的内容即可,以减少重复的工作量。内容即可,以减少重复的工作量。 C+C+提供的继提供的继承机制就是为了解决这个问题。承机制就是为了解决这个问题。 在在C+中所谓中所谓“

4、继承继承”就是在一个已存在的类的基就是在一个已存在的类的基础上建立一个新的类。础上建立一个新的类。已存在的类称为已存在的类称为“基类基类(base class)”或或“父类父类(father class)”。新建立的类称为新建立的类称为“派生类派生类(derived class)”或或“子类子类(son class)”。 5.1 派生和继承的相关概念和作用派生和继承的相关概念和作用6class Student1: public Student/声明基类是声明基类是Studentprivate: int age; /新增加的数据成员新增加的数据成员 string addr; /新增加的数据成员新

5、增加的数据成员public: void display_1( ) /新增加的成员函数新增加的成员函数 coutage: ageendl; coutaddress: addrendl; ;5.1 派生和继承的相关概念和作用派生和继承的相关概念和作用7类类A派生类派生类B:类:类A为基类,类为基类,类B为派生类。为派生类。AB新增加的成员数新增加的成员数据和成员函数据和成员函数5.1 派生和继承的相关概念和作用派生和继承的相关概念和作用8在在C+语言中,语言中,一个派生类可以从一个基类派生,一个派生类可以从一个基类派生,也可以从多个基类派生。也可以从多个基类派生。从一个基类派生的继承称为单继承;从

6、一个基类派生的继承称为单继承;从二个或多个基类派生的继承称为多重继承。从二个或多个基类派生的继承称为多重继承。通过继承机制,可以利用已有的数据类型来定义新通过继承机制,可以利用已有的数据类型来定义新的数据类型。的数据类型。所定义的新的数据类型不仅拥有新定所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。义的成员,而且还同时拥有旧的成员。5.1 派生和继承的相关概念和作用派生和继承的相关概念和作用9在建立派生类的过程中,基类不会做任何改变;在建立派生类的过程中,基类不会做任何改变;派生类则除了继承基类的所有可引用的成员变量派生类则除了继承基类的所有可引用的成员变量和成员函数外,还

7、可另外定义本身的成员变量和和成员函数外,还可另外定义本身的成员变量和处理这些变量的函数处理这些变量的函数由于派生类可继承基类的成员变量和成员函数,由于派生类可继承基类的成员变量和成员函数,因此在基类中定义好的数据和函数等的程序代码因此在基类中定义好的数据和函数等的程序代码可重复使用,这样可以提高程序的可靠性。可重复使用,这样可以提高程序的可靠性。5.1 派生和继承的相关概念和作用派生和继承的相关概念和作用10当从已有的类中派生出新的类时,可以对派生类做当从已有的类中派生出新的类时,可以对派生类做以下几种变化:以下几种变化:1、 可以继承基类的成员数据或成员函数。可以继承基类的成员数据或成员函数

8、。2、可以增加新的成员变量。、可以增加新的成员变量。3、可以增加新的成员函数。、可以增加新的成员函数。4、可以重新定义已有的成员函数。、可以重新定义已有的成员函数。5、可以改变现有的成员属性。、可以改变现有的成员属性。5.1 派生和继承的相关概念和作用派生和继承的相关概念和作用11类类A派生类派生类B:类:类A为基类,类为基类,类B为派生类。为派生类。AB 但派生并不是简单的扩充,有可能改变派生类中的基类的但派生并不是简单的扩充,有可能改变派生类中的基类的成员性质。成员性质。 有三种派生方式:公有派生、保护派生、私有派生。有三种派生方式:公有派生、保护派生、私有派生。 默认的是私有派生。默认的

9、是私有派生。class B:public A.; class B:protected A.; class B:private A.; class B: A .; A为私有派生为私有派生5.2 三种继承的派生类的成员访问方式三种继承的派生类的成员访问方式12从一个基类派生一个类的一般格式为:从一个基类派生一个类的一般格式为:class ClassName:BaseClassName private: .; /私有成员说明私有成员说明 public: .; /公有成员说明公有成员说明 protected: .; /保护成员说明保护成员说明 派生类名派生类名基类名基类名继承方式继承方式public:

10、 表示公有基类表示公有基类private:表示私有基类表示私有基类(默认默认)protected:表示保护基类表示保护基类派生类中新增加的成员派生类中新增加的成员5.2 三种继承的派生类的成员访问方式三种继承的派生类的成员访问方式13公有派生class ClassName: public BaseClassName公有派生时,公有派生时,基类中所有成员在派生类中保持各个成员基类中所有成员在派生类中保持各个成员的访问权限的访问权限。公有派生,派生类中保持公有派生,派生类中保持基类的成员特性基类的成员特性基类成员属性基类成员属性派生类中派生类中派生类外派生类外公有公有可以引用可以引用可以引用可以引

11、用保护保护可以引用可以引用不可引用不可引用私有私有不可引用不可引用不可引用不可引用5.2 三种继承的派生类的成员访问方式三种继承的派生类的成员访问方式14x(私有私有)y(保护保护)z(公有公有)Getx()Gety()ShowA()Ax(私私有私私有)y(保护保护)z(公有公有)Getx()Gety()ShowA()Bm(私有私有)n(私有私有)B()Show()Sum()publicx在类在类B新增成员中不能直接调用新增成员中不能直接调用y在类在类B中可以调用中可以调用z在整个文件中可以调用在整个文件中可以调用对类对类B的对象初始化即是对的对象初始化即是对x,y,z,m,n等全部成员的初始

12、化等全部成员的初始化5.2 三种继承的派生类的成员访问方式三种继承的派生类的成员访问方式15class A int x;protected: int y;public: int z; A(int a,int b,int c)x=a;y=b;z=c;/基类初始化基类初始化 int Getx( )return x;/返回返回x int Gety( )return y;/返回返回y void ShowA( )cout x=xty=ytz=zn;class B:public Aint m,n;public:B(int a,int b,int c,int d,int e):A(a,b,c)m=d;n=e

13、; void Show( )cout“m=mt“n=nn; coutx=Getx( )ty=ytz=zn; int Sum( )return ( Getx( )+y+z+m+n); ;void main( ) B b1(1,2,3,4,5); b1.ShowA( ); b1.Show( ); cout Sum=b1.Sum( )n;coutx=b1.Getx( )t; cout y= b1.Gety( )t; cout z=b1.zn;公有派生公有派生对基类初始化对基类初始化因为因为x是基类私有,所是基类私有,所以在派生类和类外中以在派生类和类外中不能直接引用不能直接引用因为因为y是基类保护,

14、所以在是基类保护,所以在派生类中可以直接引用。而派生类中可以直接引用。而在类外不可直接引用。在类外不可直接引用。因为因为z是基类公有,是基类公有,所以在派生类中和类所以在派生类中和类外均可直接引用。外均可直接引用。5.2 三种继承的派生类的成员访问方式三种继承的派生类的成员访问方式仅对派生类中的新增成员仅对派生类中的新增成员进行初始化进行初始化16私有派生class ClassName: private BaseClassName此时,基类中公有成员和保护成员在派生类中均变为私有,在派生类中此时,基类中公有成员和保护成员在派生类中均变为私有,在派生类中仍可直接使用这些成员,仍可直接使用这些成员

15、,基类中的私有成员,在派生类中不可直接使用。基类中的私有成员,在派生类中不可直接使用。基类成员属性基类成员属性派生类派生类派生类外派生类外公有公有可以引用可以引用不可引用不可引用保护保护可以引用可以引用不可引用不可引用私有私有不可引用不可引用不可引用不可引用基类:基类:public: (变为私有变为私有)在派生类中使用,类外不可使用在派生类中使用,类外不可使用protected: (变为私有)在派生类中使用,类外不可使用变为私有)在派生类中使用,类外不可使用private: 不能在派生类中和类外使用不能在派生类中和类外使用5.2 三种继承的派生类的成员访问方式三种继承的派生类的成员访问方式17

16、x(私有私有)y(保护保护)z(公有公有)Getx()Gety()ShowA()Ax(私私有私私有)y(私有私有)z(私有私有)Getx()Gety()ShowA()Bm(私有私有)n(私有私有)B()Show()Sum()privatex在类在类B新增加的成员中新增加的成员中不能直接调用不能直接调用y在类在类B中可以调用中可以调用z在类在类B中可以调用中可以调用对类对类B的对象初始化即是对的对象初始化即是对x,y,z,m,n等全部成员的初始化等全部成员的初始化均为私均为私有类有类B 外不能外不能引用引用5.2 三种继承的派生类的成员访问方式三种继承的派生类的成员访问方式18class A i

17、nt x;protected: int y;public: int z; A(int a,int b,int c)x=a;y=b;z=c;/基类初始化基类初始化 int Getx()return x;/返回返回x int Gety()return y;/返回返回y void ShowA()cout x=xty=ytz=zn;class B:private Aint m,n;public: B(int a,int b,int c,int d,int e):A(a,b,c)m=d;n=e; void Show()cout“m=mt“n=nn; coutx=Getx()ty=ytz=zn; int

18、Sum()return ( Getx()+y+z+m+n); ;void main(void) B b1(1,2,3,4,5); b1.ShowA(); b1.Show(); cout Sum=b1.Sum()n;coutx=b1.Getx()t; cout y= b1.Gety()t;cout z=b1.zn;私有派生私有派生对基类初始化对基类初始化因为因为x是基类私有,所以在派生类和类外中不能直接引用是基类私有,所以在派生类和类外中不能直接引用y是基类保护,所以在派生类是基类保护,所以在派生类中可以直接引用。而在类外不中可以直接引用。而在类外不可直接引用。可直接引用。z是基类公有,私有是基

19、类公有,私有派生变为私有,所以派生变为私有,所以在派生类中可直接引在派生类中可直接引用,用,而在类外不可。而在类外不可。这些函数都是基类公有,这些函数都是基类公有,在类外不可使用。在类外不可使用。A a1(1,2,3); a1.ShowA();19保护派生class ClassName: protected BaseClassName此时,基类中公有和保护成员在派生类中均变为保护的,在派生类中仍此时,基类中公有和保护成员在派生类中均变为保护的,在派生类中仍可直接使用这些成员,可直接使用这些成员,基类中的私有成员,在派生类中不可直接使用。基类中的私有成员,在派生类中不可直接使用。基类成员属性基类

20、成员属性派生类派生类派生类外派生类外公有公有可以引用可以引用不可引用不可引用保护保护可以引用可以引用不可引用不可引用私有私有不可引用不可引用不可引用不可引用基类:基类:public: (变为保护变为保护)在派生类中使用,类外不可使用在派生类中使用,类外不可使用protected: (仍为保护)在派生类中使用,类外不可使用仍为保护)在派生类中使用,类外不可使用private: 不能在派生类中和类外使用不能在派生类中和类外使用5.2 三种继承的派生类的成员访问方式三种继承的派生类的成员访问方式20 x(私有私有)y(保护保护)z(公有公有)Getx()Gety()ShowA()Ax(私私有私私有)

21、y(保护保护)z(保护保护)Getx()Gety()ShowA()Bm(私有私有)n(私有私有)B()Show()Sum()protectedx在类在类B新增加的成员中不新增加的成员中不能直接调用能直接调用y在类在类B中可以调用中可以调用z在类在类B中可以调用中可以调用对类对类B的对象初始化即是对的对象初始化即是对x,y,z,m,n等全部成员的初始化等全部成员的初始化均为保护均为保护类类B 外不外不能引用能引用5.2 三种继承的派生类的成员访问方式三种继承的派生类的成员访问方式21protected 成员是一种具有血缘关系内外有别的成成员是一种具有血缘关系内外有别的成员。员。它对派生类的对象而

22、言,是公开成员,可以访问,它对派生类的对象而言,是公开成员,可以访问,对对血缘外部而言,与私有成员一样被隐蔽血缘外部而言,与私有成员一样被隐蔽。5.2 三种继承的派生类的成员访问方式三种继承的派生类的成员访问方式22 当定义了一个类,当定义了一个类,这个类这个类只能用作基类只能用作基类来派生出来派生出新的类,而不能用这种类来定义对象时,称这种新的类,而不能用这种类来定义对象时,称这种类为抽象类。类为抽象类。 当对某些特殊的对象要进行很好地封装时,需要当对某些特殊的对象要进行很好地封装时,需要定义抽象类。定义抽象类。 将类的构造函数或析构函数的访问权限定义为将类的构造函数或析构函数的访问权限定义

23、为保保护护的时,这种类为的时,这种类为抽象类抽象类。5.3 抽象类与保护的成员函数抽象类与保护的成员函数23当把类中的构造函数或析构函数说明为当把类中的构造函数或析构函数说明为私有私有的时,的时,所定义的类通常是没有任何实用意义的,一般情况所定义的类通常是没有任何实用意义的,一般情况下,不能用它来产生对象,也不能用它来产生派生下,不能用它来产生对象,也不能用它来产生派生类。类。 5.3 抽象类与保护的成员函数抽象类与保护的成员函数24x(私有私有)y(私有私有)A( )(保护保护)ShowA()(公有公有)Ax(私私有私私有)y(私私有私私有)A( )(保护保护)ShowA()Bm(私有私有)

24、B()Show()public在类在类B中不能定义中不能定义A的对象的对象在任何时候都不能定义在任何时候都不能定义A的对象的对象但可以在初始化类但可以在初始化类B的对象时初始化的对象时初始化原类原类A中的成员中的成员,因为,因为A()在类在类B中是可以被调用的。中是可以被调用的。5.3 抽象类与保护的成员函数抽象类与保护的成员函数25class A int x, y;protected: A(int a,int b) x=a; y=b;/基类初始化基类初始化public:void ShowA( )cout x=xty=yn;class B: public Aint m;A a1;/在派生类中也

25、不可以定义在派生类中也不可以定义A的对象,实际上还是类外调用的对象,实际上还是类外调用public: B(int a,int b,int c):A(a,b)/可以在派生类中调用可以在派生类中调用A的构造函数的构造函数 m=c; void Show( ) cout“m=mn; ShowA(); ;void main( ) B b1(1,2,3); /可以定义派生类对象可以定义派生类对象 b1.Show( ); A aa;/不可定义不可定义A的对象的对象 a1(4,5)5.3 抽象类与保护的成员函数抽象类与保护的成员函数26可以用多个基类来派生一个类。可以用多个基类来派生一个类。ABCD多重继承是

26、单多重继承是单一继承的扩展一继承的扩展派生类中新定派生类中新定义的成员义的成员5.4 多重继承多重继承27格式为:格式为:class 类名类名:类名类名1,., 类名类名n private: . ; /私有成员说明私有成员说明; public: . ; /公有成员说明公有成员说明; protected: . ; /保护的成员说明保护的成员说明;继承方式继承方式class D: public A, protected B, private C ./派生类中新增加成员派生类中新增加成员;5.4 多重继承多重继承28class A int x1,y1;public: A(int a,int b) x

27、1=a; y1=b;void ShowA(void) coutA.x=x1tA.y=y1endl; ;class Bint x2,y2;public: B(int a,int b)x2=a; y2=b; void ShowB( ) coutB.x=x2tB.y=y2endl; ;class C:public A,private Bint x,y;public: C(int a,int b,int c,int d,int e,int f):A(a,b),B(c,d)x=e; y=f; void ShowC( )coutC.x=xtC.y=yendl;ShowA();ShowB();void ma

28、in( )C c(1,2,3,4,5,6);c.ShowC();c.ShowA ();c.ShowB (); 公有派生公有派生私有派生私有派生仍为公有仍为公有成为私有成为私有非法,私有类外不可调用非法,私有类外不可调用B b1(10,20);b1.ShowB();29由于构造函数不能被继承由于构造函数不能被继承,故故派生类的构造函数派生类的构造函数必须调用基类的构造函数必须调用基类的构造函数来初始化基类成员和基来初始化基类成员和基类类子对象子对象。若派生类中含有子对象,则派生类构造函若派生类中含有子对象,则派生类构造函数的调用顺序如下:数的调用顺序如下:基类的构造函数基类的构造函数子对象类的构

29、造函数子对象类的构造函数派生类的构造函数派生类的构造函数5.5 有子对象的派生类的构造函数有子对象的派生类的构造函数30class B:public A int y; A a1;public: B(int a, int b):A(a),a1(3)y=b; .;当撤销派生类对象时,析构函当撤销派生类对象时,析构函数的调用正好相反。数的调用正好相反。基类的构造函数基类的构造函数子对象类的构造函数子对象类的构造函数派生类的构造函数派生类的构造函数5.5 有子对象的派生类的构造函数有子对象的派生类的构造函数基类成员构造用基类名,基类成员构造用基类名,基类子对象构造用对象名基类子对象构造用对象名基类成员

30、构造基类成员构造基类子对象构造基类子对象构造31class Base1 int x;public: Base1(int a)x=a;cout调用基类调用基类1的构造函数的构造函数!n;Base1( )cout调用基类调用基类1的析构函数的析构函数!n;class Base2 int y;public: Base2(int a)y=a;cout调用基类调用基类2的构造函数的构造函数!n;Base2( )cout调用基类调用基类2的析构函数的析构函数!n;class Derived:public Base2, public Base1int z;public: Derived(int a,int

31、b):Base1(a),Base2(20) z=b; cout调用派生类的构造函数调用派生类的构造函数!n;Derived( )cout调用派生类的析构函数调用派生类的析构函数!n;void main( )Derived c(100,200);调用基类调用基类2的构造函数的构造函数调用基类调用基类1的构造函数的构造函数调用派生类的构造函数调用派生类的构造函数调用派生类的析构函数调用派生类的析构函数调用基类调用基类1的析构函数的析构函数调用基类调用基类2的析构函数的析构函数先说明基类先说明基类25.5 有子对象的派生类的构造函数有子对象的派生类的构造函数32class Derived:publi

32、c Base2, public Base1int z; Base1 b1,b2; public: Derived(int a,int b):Base1(a),Base2(20), b1(200),b2(a+b) z=b; cout调用派生类的构造函数调用派生类的构造函数!n; Derived( )cout调用派生类的析构函数调用派生类的析构函数!n;void main( )Derived c(100,200);基类子对象基类子对象基类成员构造基类成员构造基类子对象构造基类子对象构造基类成员构造用基类名,基类成员构造用基类名,基类子对象构造用对象名基类子对象构造用对象名5.5 有子对象的派生类的

33、构造函数有子对象的派生类的构造函数33class Base1 int x;public: Base1(int a)x=a;cout调用基类调用基类1的构造函数的构造函数!n;Base1( )cout调用基类调用基类1的析构函数的析构函数!n;class Base2 int y;public: Base2(int a)y=a;cout调用基类调用基类2的构造函数的构造函数!n;Base2( )cout调用基类调用基类2的析构函数的析构函数!n;class Derived:public Base2, public Base1int z; Base1 b1,b2; public: Derived(i

34、nt a,int b):Base1(a),Base2(20), b1(200),b2(a+b) z=b; cout调用派生类的构造函数调用派生类的构造函数!n;Derived( )cout调用派生类的析构函数调用派生类的析构函数!n;void main( )Derived c(100,200);5.5 有子对象的派生类的构造函数有子对象的派生类的构造函数34调用基类调用基类2的构造函数的构造函数调用基类调用基类1的构造函数的构造函数调用派生类的构造函数调用派生类的构造函数调用派生类的析构函数调用派生类的析构函数调用基类调用基类1的析构函数的析构函数调用基类调用基类2的析构函数的析构函数调用基类

35、调用基类1的构造函数的构造函数调用基类调用基类1的构造函数的构造函数调用基类调用基类1的析构函数的析构函数调用基类调用基类1的析构函数的析构函数说明基类说明基类1的对象的对象b1,b25.5 有子对象的派生类的构造函数有子对象的派生类的构造函数35冲突冲突ABCxxxDxxxD()dD v;v.x=5;public派生类对象派生类对象产生了冲突产生了冲突v.A:x=5;用类作用符限定用类作用符限定5.6 多重继承引起的二义性多重继承引起的二义性36class Apublic: int x; void Show()cout x=xn; A(int a=0)x=a;class Bpublic: i

36、nt x; void Show()cout x=xn; B(int a=0)x=a;class C:public A,public Bint y;public: void Setx(int a) x=a; /c1对象中有两个对象中有两个x成员成员 void Sety(int b)y=b; int Gety() return y;void main( )C c1;c1.Show(); /c1对象中有两个对象中有两个Show()函数函数 这时,可以利用这时,可以利用类作用类作用域符域符:来指明数据或函来指明数据或函数的来源。数的来源。如:如:A:x=a; c1.B:Show();5.6 多重继承引

37、起的二义性多重继承引起的二义性37支配规则支配规则AxDpublicxxD()基类成员基类成员派生类新派生类新增成员增成员D v;v.x=5;当派生类中新增加的数据或函当派生类中新增加的数据或函数与基类中原有的同名时,若数与基类中原有的同名时,若不加限制,则不加限制,则优先调用派生类优先调用派生类中的成员中的成员,即后面的覆盖前面的即后面的覆盖前面的。55.6 多重继承引起的二义性多重继承引起的二义性38class Apublic: int x;void Show()cout x=xn;class Bpublic: int y;void Show()cout y=yn;class C:publ

38、ic A,public Bpublic: int y; /类类B和类和类C均有均有y的成员的成员;void main( ) C c1; c1.x=100; c1.y=200;/给派生类中的给派生类中的y赋值赋值 c1.B:y=300; /给基类给基类B中的中的y赋值赋值 c1.A:Show(); c1.B:Show();/用作用域运算符限定调用的函数用作用域运算符限定调用的函数 cout y=c1.yn;/输出派生类中的输出派生类中的y值值 cout y=c1.B:yn;/输出基类输出基类B中的中的y值值当派生类中新增加的当派生类中新增加的数据或函数与基类中数据或函数与基类中原有的同名时,若不

39、原有的同名时,若不加限制,则加限制,则优先调用优先调用派生类中的成员,派生类中的成员,即即后面的覆盖前面的后面的覆盖前面的。5.6 多重继承引起的二义性多重继承引起的二义性39class Apublic: int x;A(int a=0) x=a;class Bpublic: int y;B(int a=0) y=a;class C:public Aint z;B b1; A a1;public: C(int a,int b,int m):A(a),b1(b),a1(a+b) z=m; void Show( )coutx=xt;couty=b1.yt;coutx=zn;couta1.x=a1.

40、xendl; ;void main( )C c1(100,200,500); c1.Show(); xzShow()a1.xb1.yC的对象所占空间的对象所占空间从基类从基类A中继承中继承在类在类C中新说明中新说明在类在类C中新说明中新说明在类在类C中新说明中新说明在类在类C中新说明中新说明从基类从基类A中继承中继承新说明类新说明类A对象中的对象中的x5.6 多重继承引起的二义性多重继承引起的二义性40基类与对象成员基类与对象成员 任一基类在派生类中只能继承一次,否则,会造成成员名任一基类在派生类中只能继承一次,否则,会造成成员名的冲突的冲突 若在派生类中,确实要有二个以上基类的成员,若在派生

41、类中,确实要有二个以上基类的成员,则可用基则可用基类的二个对象作为派生类的成员。类的二个对象作为派生类的成员。 把一个类作为派生类的基类或把一个类的对象作为一个类把一个类作为派生类的基类或把一个类的对象作为一个类的成员,在使用上是有区别的:的成员,在使用上是有区别的:p 在派生类中可直接使用基类的成员(访问权限允许的话),在派生类中可直接使用基类的成员(访问权限允许的话),但要但要使用对象成员的成员时,必须在对象名后加上成员运使用对象成员的成员时,必须在对象名后加上成员运算符算符“.”和成员名和成员名。5.6 多重继承引起的二义性多重继承引起的二义性41例题:在平面上作两个点,连一直线,求直线

42、的长度和直例题:在平面上作两个点,连一直线,求直线的长度和直线中点的坐标。要求如下:线中点的坐标。要求如下: 基类为基类为Dot,有两个公有数据成员,即平面上的坐标,有两个公有数据成员,即平面上的坐标(x,y),同时有构造函数及打印函数。,同时有构造函数及打印函数。 派生类为派生类为Line,有,有两个基类两个基类Dot对象对象,分别存放两点的,分别存放两点的坐标,同时,从坐标,同时,从基类继承了一个基类继承了一个Dot数据数据,存放直线中,存放直线中点的坐标。点的坐标。5.7 应用举例应用举例xyDot(x,y)(构造构造)Dot(&dot)(拷贝拷贝)Show()Dot的对象空间的

43、对象空间x(中点中点)y(中点中点)Show()d1xyShow()d2xyShow()Line(dot1,dot2)Showl()Line对象对象空间空间从基从基类继类继承承基类基类对象对象425.7 应用举例应用举例43class Dotpublic: float x,y;Dot(float a=0,float b=0) x=a; y=b;void Show(void)coutx=xty=yendl;class Line:public DotDot d1,d2;public: Line(Dot dot1,Dot dot2):d1(dot1),d2(dot2) x=(d1.x+d2.x)/2

44、; y=(d1.x+d2.y)/2; void Showl( ) coutDot1: ; d1.Show(); coutDot2: ; d2.Show(); coutLength=sqrt(d1.x-d2.x)*(d1.x-d2.x)+(d1.y-d2.y)*(d1.y-d2.y); coutendl; coutCenter: x=xty=yendl; ;void main( ) float a,b; coutab; Dot dot1(a,b);/调用调用Dot的构造函数的构造函数 coutab; Dot dot2(a,b); Line line(dot1,dot2); line.Showl(

45、);用坐标初始化用坐标初始化Dot对象对象在在Line中新说明的成员中新说明的成员对成员初始化对成员初始化x,y是继承基类的成员是继承基类的成员打印坐标打印坐标5.7 应用举例应用举例44基类基类对象对象派生类派生类对象对象赋值兼容规则,即相互之间能否赋值?赋值兼容规则,即相互之间能否赋值? 可以将派生类对象的值赋给基类对象。可以将派生类对象的值赋给基类对象。反之不行反之不行Base b;Derive d; b = d; 只是将从基类只是将从基类继承来的成员继承来的成员赋值。赋值。5.8 基类与派生类的转换基类与派生类的转换45Dot dot;Line line;Dot = line;Line

46、 = dot;非法非法xyDot(x,y)(构造构造)Dot(&dot)(拷贝拷贝)Show()x(中点中点)y(中点中点)Show()d1xyShow()d2xyShow()Line(dot1,dot2)Showl()Line对象空间对象空间从基从基类继类继承承基类基类对象对象Dot的对象空间的对象空间5.8 基类与派生类的转换基类与派生类的转换46可以将一个派生类对象的地址赋给基类的指针变量。可以将一个派生类对象的地址赋给基类的指针变量。基类对象基类对象派生类对象派生类对象Base b;Derive d;Base *basep;basepbasep=&b;basepbase

47、p = &dbasep只能引用从基类只能引用从基类继承来的成员。继承来的成员。基类指针基类指针派生类对象派生类对象基类对象基类对象5.8 基类与派生类的转换基类与派生类的转换47派生类对象可以初始化基类的引用。派生类对象可以初始化基类的引用。Derive d;Base& basei=d;基类对象基类对象派生类对象派生类对象Base b;Derive d;别名别名baseibasei只能引用从基只能引用从基类继承来的成员。类继承来的成员。基类引用基类引用派生类对象派生类对象5.8 基类与派生类的转换基类与派生类的转换48class Apublic: int x;A(int a=0

48、) x=a;class Bpublic: int y;B(int a=0) y=a;class C:public A,public B int z;public: C(int a,int b,int m): A(a), B(b) z=m; void Show( )coutx=xt;couty=yt;coutz=zn;void main(void)A a1(100);B b1(200);C c1(10,20,50);couta1.x=a1.xendl;coutb1.y=b1.yendl;c1.Show();a1=c1; b1=c1;/派生类对象向基类对象赋值派生类对象向基类对象赋值couta1.

49、x=a1.xendl;coutb1.y=b1.yShow(); xyzC( )Show( )102050a1.x=100b1.y=200 x=10y=20z=50a1.x=10b1.y=20c1xA( )a1yB( )b11002001020错误!错误!49类类B 是类是类A的派生类的派生类xA()xA()yB()xA()zC()A类类B类类C类类dxD()xA()zC()yB()A()xD类类类类A拷贝拷贝类类C 是类是类A的派生类的派生类类类D 是类是类B和类和类C的派生类的派生类这样,类这样,类D中就有两份类中就有两份类A的拷贝的拷贝B类类C类类类类A拷贝拷贝5.9 虚基类虚基类50这种同一个公共的基类在这种同一个

温馨提示

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

评论

0/150

提交评论