OOP继承与派生课堂PPT

上传人:博****1 文档编号:591342534 上传时间:2024-09-17 格式:PPT 页数:43 大小:214KB
返回 下载 相关 举报
OOP继承与派生课堂PPT_第1页
第1页 / 共43页
OOP继承与派生课堂PPT_第2页
第2页 / 共43页
OOP继承与派生课堂PPT_第3页
第3页 / 共43页
OOP继承与派生课堂PPT_第4页
第4页 / 共43页
OOP继承与派生课堂PPT_第5页
第5页 / 共43页
点击查看更多>>
资源描述

《OOP继承与派生课堂PPT》由会员分享,可在线阅读,更多相关《OOP继承与派生课堂PPT(43页珍藏版)》请在金锄头文库上搜索。

1、上次课回顾上次课回顾q 继承与派生的基本概念继承与派生的基本概念q访问权限控制访问权限控制q派生构造函数与析构函数派生构造函数与析构函数q多继承基础多继承基础第第3单元单元 继承与派生继承与派生q二义性问题二义性问题q同名覆盖同名覆盖q虚基类虚基类q聚合类聚合类q多多继继承承时时,基基类类与与派派生生类类之之间间,或或基基类类与与基基类类之之间间出出现现同同名名成成员员时时,将将出出现现访访问问时时的的二二义义性性(不不确确定定性性),这这时时我我们们常常采采用用虚虚函函数数或或支支配配(即即同名覆盖)同名覆盖)原则原则来解决。来解决。q当当派派生生类类从从多多个个基基类类派派生生,而而这这些

2、些基基类类又又从从同同一一个个基基类类派派生生,则则在在访访问问此此共同基类中的成员共同基类中的成员时,将产生二义性,此时一般采用时,将产生二义性,此时一般采用虚基类虚基类来解决。来解决。一、什么是二义性一、什么是二义性3.5 二义性问题二义性问题class A public: void f( );class B public: void f( ); void g( );class C: public A, piblic B public: void g( ); void h( );如果声明:如果声明:C c1;则则 c1.f( ); 具有二义性具有二义性而而 c1.g( ); 无二义性(同名

3、覆盖)无二义性(同名覆盖)例如,例如,3.5 二义性问题二义性问题1. 用用类名类名来限定来限定c1.A:f( ) 或或 c1.B:f( )2. 同名覆盖同名覆盖在类在类C 中声明一个同名成员函数中声明一个同名成员函数f(),f()再根据需要调用再根据需要调用 :A:f() 或或B:f()二、解决方法二、解决方法3.5 二义性问题二义性问题class B public: int b;class B1 : public Bprivate: int b1;class B2 : public Bprivate: int b2;class C : public B1,public B2public:

4、int f( );private: int d;例如,例如,3.5 二义性问题二义性问题下面的访问是二义性的:下面的访问是二义性的:C c;c.b 而下面是正确的:而下面是正确的:c.B1:bc.B2:b3.5 二义性问题二义性问题访问共同基类访问共同基类B中的成员中的成员b当派生类与基类中有相同成员时:当派生类与基类中有相同成员时:若未强行指名,则通过派生类对象使用的是派生类中的同名成员。若未强行指名,则通过派生类对象使用的是派生类中的同名成员。如要通过派生类对象访问基类中被覆盖的同名成员,应使用如要通过派生类对象访问基类中被覆盖的同名成员,应使用基类名限定基类名限定。3.6 同名覆盖同名覆

5、盖class B1/声明基类声明基类B1public:int nV;void fun( )coutMember of B1endl;class B2/声明基类声明基类B2 public:int nV;void fun( )coutMember of B2endl;例:多继承同名覆盖举例例:多继承同名覆盖举例3.6 同名覆盖同名覆盖class D1: public B1, public B2 public:int nV;/同名数据成员同名数据成员void fun( )/同名函数成员同名函数成员coutMember of D1endl;3.6 同名覆盖同名覆盖void main( )D1 d1;d

6、1.nV=1; /对象名对象名.成员名标识成员名标识, 访问访问D1类成员类成员d1.fun( ); d1.B1:nV=2;/作用域分辨符标识作用域分辨符标识, 访问基类访问基类B1成员成员d1.B1:fun( ); d1.B2:nV=3;/作用域分辨符标识作用域分辨符标识, 访问基类访问基类B2成员成员d1.B2:fun( );3.6 同名覆盖同名覆盖在派生类中对基类成员的访问应该是唯一的。在派生类中对基类成员的访问应该是唯一的。但但是是,在在多多继继承承方方式式下下,可可能能造造成成对对基基类类中中某某个个成成员员的的访访问问出出现现不不唯唯一一的情况,称为的情况,称为对基类成员访问的二义

7、性对基类成员访问的二义性问题。问题。解决的办法:解决的办法:q用作用域运算符用作用域运算符“:”进行限定;进行限定;q设置设置虚基类虚基类来解决此问题。来解决此问题。3.7 虚基类虚基类在在派派生生类类的的对对象象中中,这这些些同同名名成成员员在在内内存存中中同同时时拥拥有有多多个个副副本本,如如果果将将直直接接基基类类的的共共同同基基类类设设置置为为虚虚基基类类,那那么么从从不不同同的的路路径径继继承承过过来来的的该该类类成成员员在在内内存存中中只只拥拥有有一一个个副副本本,从从而而解解决决了了同同名名成成员员的的唯唯一一标标识识问题问题class :virtual 一、虚基类的定义格式一、

8、虚基类的定义格式3.7 虚基类虚基类class Apublic: A()a=10;protected: int a;class A1:virtual public A /定义虚基类定义虚基类public: A1()coutaendl;class A2:virtual public A public: A2()coutaendl;class B:A1,A2 /缺省为私有继承缺省为私有继承public: B()coutaendl; ;void main() B obj;3.7 虚基类虚基类例例: :虚虚基基类类的的初初始始化化与与一一般般多多继继承承的的初初始始化化在在语语法法上上相相同同,但但构

9、构造造函函数数的的调调用顺序有所不同用顺序有所不同。规则如下:规则如下:A.先调用虚基类的构造函数,再调用非虚基类的构造函数。先调用虚基类的构造函数,再调用非虚基类的构造函数。B.若同一层次中包含多个虚基类,其调用顺序按若同一层次中包含多个虚基类,其调用顺序按定义时顺序定义时顺序。C.若若虚虚基基类类由由非非虚虚基基类类派派生生而而来来,则则仍仍按按先先调调用用基基类类构构造造函函数数,再再调用派生类构造函数的顺序。调用派生类构造函数的顺序。二、虚基类的初始化二、虚基类的初始化3.7 虚基类虚基类class Base1public: Base1()coutclass Base1endl;cla

10、ss Base2public: Base2()coutclass Base2endl;class Level1:public Base2,virtual public Base1 /定义虚基类定义虚基类public: Level1()coutclass Level1endl;3.7 虚基类虚基类下例演示了引入虚基类后构造函数的调用顺序。下例演示了引入虚基类后构造函数的调用顺序。class Level2:public Base2,virtual public Base1 public: Level2()coutclass Level2endl;class TopLevel:public Leve

11、l1,virtual public Level2 public: TopLevel()coutclass TopLevelendl;void main() TopLevel obj;3.7 虚基类虚基类运行结果运行结果:class Base1class Base2class Level2class Base2class Level1class TopLevel13.7 虚基类虚基类定义虚基类的构造函数注意:定义虚基类的构造函数注意:q一般情况下虚基类只允许定义不带参数的或带缺省参数的构造函数;一般情况下虚基类只允许定义不带参数的或带缺省参数的构造函数;q如果多继承不牵扯到对同一基类的派生,就没

12、必要定义虚基类。如果多继承不牵扯到对同一基类的派生,就没必要定义虚基类。3.7 虚基类虚基类class Data_rec /定义基类定义基类Data_recpublic:Data_rec()name=NULL;Data_rec()delete name;void insert_name(char* pname)delete name;name=new charstrlen(pname)+1;strcpy(name,pname);void print()coutName:nameendl;private:char* name;3.7 虚基类虚基类下例演示了虚基类的应用。下例演示了虚基类的应用。c

13、lass Student:virtual public Data_rec /定义虚基类定义虚基类public:Student():Data_rec()id=NULL;Student()delete id;void insert_id(char* pid)delete id;id=new charstrlen(pid)+1;strcpy(id,pid);void print()Data_rec:print(); /访问基类的成员函数访问基类的成员函数coutId:idendlendl;private:char* id; 3.7 虚基类虚基类class Teacher:virtual public

14、 Data_rec /定义虚基类定义虚基类public:Teacher():Data_rec()sal=0;void insert_sal(float psal)sal=psal;void print()Data_rec:print(); /访问基类的成员函数访问基类的成员函数coutSal:salendl;private:float sal;3.7 虚基类虚基类class Postgrad:public Student /定义派生类定义派生类Postgradpublic:Postgrad():Student()dn=NULL;void insert_dn(char* p)delete dn;

15、dn=new charstrlen(p)+1;strcpy(dn,p);void print()Student:print(); /访问基类的成员函数访问基类的成员函数coutDept Name:dnyabbaDabbaDo();/错误:错误:Fred类的对象在定义之前被使用类的对象在定义之前被使用 private: Fred* x; /正确,经过前向引用声明,可以声明正确,经过前向引用声明,可以声明Fred类的对象指针类的对象指针;class Fred public: void yabbaDabbaDo();private: Barney* y; 3.8 聚合类聚合类总的来说,应该记住:总的

16、来说,应该记住:当使用前向引用声明时,只能使用被声明的符号,而不能涉及类的任何当使用前向引用声明时,只能使用被声明的符号,而不能涉及类的任何细节。细节。3.8 聚合类聚合类如如果果一一个个聚聚合合类类,同同时时又又是是一一个个派派生生类类,那那么么它它的的构构造造函函数数初初始始化化列列表表还应负责为基类构造函数的调用提供参数。还应负责为基类构造函数的调用提供参数。当一个类既是聚合类又是派生类时的构造函数定义形式:当一个类既是聚合类又是派生类时的构造函数定义形式:: 类的初始化类的初始化 四、其它说明四、其它说明q二义性问题二义性问题q同名覆盖同名覆盖q虚基类虚基类q聚合类聚合类本次课小节本次

17、课小节作业作业1.声声明明一一个个Shape(形形状状)基基类类,它它有有两两个个派派生生类类Circle(圆圆)和和Square(正正方方形形),要要求求(1)根根据据给给出出圆圆心心的的坐坐标标,计计算算圆圆的的面面积积;(2)根据给出正方形的中点坐标和一个顶点坐标,计算正方形面积。)根据给出正方形的中点坐标和一个顶点坐标,计算正方形面积。2.提提示示:Shape类类的的数数据据成成员员包包括括中中心心点点的的坐坐标标,Circle类类和和Square类类由由Shape类类派派生生,Circle类类新新增增一一个个数数据据成成员员,即即圆圆的的半半径径,Square类新增两个数据成员,即顶点坐标。类新增两个数据成员,即顶点坐标。2.声声明明一一个个哺哺乳乳动动物物类类(Mammal),再再由由此此派派生生出出人人类类(Person)、狗狗类类(Dog)和和猫猫类类(Cat),这这些些类类中中均均有有speak( )函函数数,观观察察在在调调用用过过程中,到底使用了谁的程中,到底使用了谁的speak( )函数。函数。个人观点供参考,欢迎讨论

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 医学/心理学 > 基础医学

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号