C继承和派生类课件

上传人:公**** 文档编号:587409262 上传时间:2024-09-05 格式:PPT 页数:40 大小:348.50KB
返回 下载 相关 举报
C继承和派生类课件_第1页
第1页 / 共40页
C继承和派生类课件_第2页
第2页 / 共40页
C继承和派生类课件_第3页
第3页 / 共40页
C继承和派生类课件_第4页
第4页 / 共40页
C继承和派生类课件_第5页
第5页 / 共40页
点击查看更多>>
资源描述

《C继承和派生类课件》由会员分享,可在线阅读,更多相关《C继承和派生类课件(40页珍藏版)》请在金锄头文库上搜索。

1、第十一章 继承和派生类l类是一种抽象数据类型,是对具有共同属性和行为的对象(事物)的抽象描述。房屋平房楼房办公楼居民楼 顶层的抽象事物具有处于底层的抽象事物的共同特征,而处于底层的抽象事物除了包含顶层抽象事物的特征外,还具有自身的我特征。l 一个类继承另一个类时,这个类被称为继承类、派生类或子类,另一个类被称为被继承类、基类或父类。l 继承类包含了被继承类中的所有成员,且有自己的成员。 继承:从一个或多个先前定义过的类(称为基类)中接受全部或一部分数据(属性)或函数(行为或操作),并且补充定义新的数据或函数,因而形成一个新的低层的类(称为派生类)。而该派生类还可用作更低层派生类的基类。 cla

2、ss demo protected: int j; public: demo()j=0 void add(int i) j+=i; void display( ) coutjendl;;1 1 派生类定义的格式派生类定义的格式class child:public demo public: void sub(int i)j-=i; ;void main(void) child object,object1; object.display(); object.add(10); object.display(); object.sub(5); object.display(); object1.di

3、splay;01050l定义派生类的基本格式: class 派生类名:继承权限 基类名l继承权限:public,protected,private影响的是被继承的原基类成员的访问权限class定义的默认为private,struct定义的默认为publicl 继承权限为public时,称该派生为公有派生。公有派生。基类中的所有public成员在派生类中仍是public成员,所有protected成员在派生类中仍是protected成员。l 继承权限为private时,称该派生为私有派生。私有派生。基类中的public成员和protected成员在派生类中均变成private成员。l 继承权限为

4、protected时,称该派生为保护派保护派生。生。基类中的public成员和protected成员在派生类中均变成protected成员。成员成员被其它函数访问被其它函数访问被继承被继承publicpublic可以可以可以可以protectedprotected不可以不可以可以可以privateprivate不可以不可以不可以不可以 无论哪一种继承权限,其基类的private成员均不能为派生类所继承。但可通过被同时继承下来的原基类的某些函数间接访问它们。private:aa1protected:aa2public:aa3AClass B:public A private:bb1 protec

5、ted:bb2 public:bb3 private:bb1protected: aa2 bb2public: aa3 bb3B公有派生private:aa1protected:aa2public:aa3AClass B:protected A private:bb1 protected:bb2 public:bb3 private:bb1protected: aa2 bb2 aa3public: bb3B保护派生private:aa1protected:aa2public:aa3AClass B: A private:bb1 protected:bb2 public:bb3 private:

6、bb1 aa2 aa3protected: bb2 public: bb3B私有派生2 2 派生类的使用派生类的使用 #include class employee private: char *name; short age; float salary; public: employee( ) name=0; age=0; salary=0.0; employee(char *name1, short age1, float salary1) name=new charstrlen(name1)+1; strcpy(name,name1); age=age1; salary=salary1;

7、 void print( ) const /const成员函数:不能改变类中成成员函数:不能改变类中成 员数据的值,也不能调用类中非员数据的值,也不能调用类中非 const成员函数成员函数 cout“name:”name; cout“age:”age; cout“salary:”salaryendl; employee( ) delete name; ;Manager: 除具有除具有employee的属性外,有新的属性。为避免重复定义,的属性外,有新的属性。为避免重复定义,可从可从employee中派生出中派生出manager(派生类)。(派生类)。class manager: public

8、employee private: int level; public: manager( ) level=0; manager(char *name1, short age1, float salary1, int level1): employee(name1, age1, salary1) level=level1; void print_level( ) cout“level:”levelendl; ;派生类构造函数:派生类构造函数:使用初始化符表初始化基类中的成员。使用初始化符表初始化基类中的成员。缺省构造函数缺省构造函数若基类无缺省构造函数,将出错若基类无缺省构造函数,将出错基类定

9、义部分基类定义部分构造函数构造函数析构函数析构函数printPrint_levelnameagesalarylevel函数函数函数函数函数函数派生类新增部分派生类新增部分公有方法公有方法私有成员私有成员void main()manager m(“xyz,24,1000,2); m.print_level(); m.print(); m.employee:print();void main() manager n; n.print_level() ; n.print(); 若若a a是是Y Y从从X X类中继承来的公用成员,设类中继承来的公用成员,设y y是是Y Y的一个对象的一个对象,则可访问

10、,则可访问y.ay.a或或y.X:ay.X:aprotected 访问指明符:访问指明符:外部函数不能访问;外部函数不能访问;派生类成员函数可直接访问。派生类成员函数可直接访问。 class employee private: short age; float salary; protected: char *name; / ;派生类成员函数:派生类成员函数:void manager:print_name( ) const coutnameendl; 外部函数:外部函数: void f( ) manager m; coutm.nameendl; /错错 继续派生: class director

11、: public manager / employeedirectormanager多层继承多层继承class x protected:int i, j; public:x(int i, int j) x:i=i, x:j=j; void print() cout i= i j= j endl; ;class y : public xint k; public:y(int i, int j) : x(i, j) k = i * j; /初始化列表初始化列表void print() cout i= i j= j k=kendl; ; 支配规则(就近原则)class z : public y pu

12、blic:z(int i, int j) : y(i, j) /初始化列表初始化列表void print1() cout i= i j= jendl; void print() y:print(); ; void main()y y1(23, 45);y1.print(); y1.x:print(); z z1(10, 20);z1.print();z1.print1(); z1.y:print(); z1.x:print(); i=23 j=45 k=1035i=23 j=45i=10 j=20 k=200i=10 j=20i=10 j=20 k=200i=10 j=20l 对属于基类的成员

13、进行初始化是通过初始表中的对属于基类的成员进行初始化是通过初始表中的初始化项来初始化的。若初始化表中没有调用基类初始化项来初始化的。若初始化表中没有调用基类的初始化项,则自动调用基类的无参构造函数进行的初始化项,则自动调用基类的无参构造函数进行初始化。初始化。 l 如果派生类的自有成员和继承成员同名,则自有如果派生类的自有成员和继承成员同名,则自有成员优先,即通过这个共同的成员名所访问的是自成员优先,即通过这个共同的成员名所访问的是自有成员,而不是继承成员,这种情况下,可以在成有成员,而不是继承成员,这种情况下,可以在成员名前加类区分符将同名成员区分开。员名前加类区分符将同名成员区分开。( (

14、支配规则支配规则) )l 作用域运算符不能连续使用,即下列形式是不允作用域运算符不能连续使用,即下列形式是不允许的:许的:CName1:Cname2:CnamenCName1:Cname2:Cnamenl 作用域运算符的左操作数可以是当前对象的直接作用域运算符的左操作数可以是当前对象的直接基类,也可以是当前对象的间接基类基类,也可以是当前对象的间接基类( (祖先类祖先类) )。3 3 多重继承与冲突多重继承与冲突l由多个基类派生出一个子类称之为多重继承l在多重派生中,如果不同的基类具有名字相同的共有成员或保护成员,此时若在派生类中不正确使用它们,就会产生二义性,这种情况称之为冲突在职研究生研究

15、生教职工【例】冲突的程序示例。class A protected:int x; public:A(int a)x=a;void Show(void)coutx=xn;class B protected: int x; public: B(int a)x=a;void Show(void)coutx=xn;class C:public A, public B /多重继承多重继承 int y; public:C(int a , int b):A(a) , B(b) /多重继承的初始化多重继承的初始化 / void Setx(int a) /x=a; / / 冲突冲突 A:x=a; /正确正确( (

16、冲突的解决办法冲突的解决办法: :在成员名在成员名 前加上基类名前加上基类名) ) void Sety(int b) y=b; int Gety(void) return y;void main(void) C c1(10,100); /c1.Show(); / / 冲突冲突 c1.B:Show(); /正确正确 类B1类B2类D1类D2类Cclass B1 protected: int x; public: void Show() coutx=xn; ;class B2 protected: int x; public: void Show() coutx=xn; ;class D1:pub

17、lic B1 ;class D2:public B2 ;class C:public D2,public D1 public: /void Setx1(int a)D1:B1:x=a; / / 错误,域运算错误,域运算 符不能连续使用符不能连续使用 void Setx1(int a)D1:x=a; /正确,或为正确,或为B1:x=a;B1:x=a; void Setx2(int a)D2:x=a; /正确,或为正确,或为B2:x=a;B2:x=a; ; void main(void) C c;c.Setx1(2); /c.D1:B1:Show(); / / 错误,域运算符不能连续使用错误,域运

18、算符不能连续使用 c.SetX2(3); c.D2:Show(); /正确,或为正确,或为c.B2:Show();c.B2:Show(); 4 4 构造、析构函数的调用顺序构造、析构函数的调用顺序l构造函数的调用顺序只与派生类继承基类的顺序有关,而与初始化成员列表中构造函数顺序无关。l一个类的构造函数只能对它的直接基类的构造函数传递实参。编译器调用构造函数的次序:编译器调用构造函数的次序: 基类 成员对象 派生类编译器调用析构函数的次序:编译器调用析构函数的次序: 基类 成员对象 派生类派生类所不能继承的:派生类所不能继承的:友员关系用户定义的赋值运算符析构函数构造函数运算用户定义的 new5

19、 访问类型的调整访问类型的调整l 有时为了某种目的,需要将从派生类继承的内容的访问类型进行调整,这时可以通过访问声明进行。访问声明访问声明的一般格式为: :; 其中,必须基类的public和protected类型的成员名。l 在访问声明时仅仅说明基类成员名,即对成员数据不可以为它说明数据类型,对成员函数不可以说明参数和返回值类型。【例】 用访问声明调整访问类型class Cbaseint x; protected:int y; public:int Fun(int a,int b) return a;class CDerived:Cbase protected : /int CBase:y;

20、/错误,数据成员的访问声明中不能有类型错误,数据成员的访问声明中不能有类型 CBase:y; /正确正确 public: /int CBase:Fun(int,int); /错误,成员函数的访问声明错误,成员函数的访问声明不不 能有参数和返回值类型能有参数和返回值类型 CBase:Fun; /正确正确;l 访问声明不允许在派生类中改变基类成员的访问类型,即基类中的protected成员在派生类中只能调整为protected类型,基类中的public成员在派生类中只能调整为public类型。l 对基类中重载函数进行访问声明,将会调整基类中所有具有该名的函数的访问类型。如果在派生类中有与基类中同名

21、的函数,也允许在派生类中对该函数进行访问声明。6 6 赋值兼容规则赋值兼容规则 赋值兼容规则是指,在具有继承关系的类之间:1. 公有派生类对象可直接赋值给基类的对象2. 基类对象不可以赋给派生类对象3. 公有派生类对象的地址可赋给基类指针变量4. 公有派生类对象可以初始化基类引用5. 在将公有派生类的对象赋给基类对象之后,基类对象只能访问派生类中从基类继承的公有成员,不能访问派生类中增加的公有成员。【例】 赋值兼容规则class Cbase protected:int x; public:CBase(int a)x=a;void Show1()coutx=xn;class CDerived:p

22、ublic Cbase protected:int y; public:CDerived(int a,int b):CBase(b) y=a; void Show1()couty=yn;void Show2()couty=yShow1();/Eb3.Show1();/F/c=b1; /错误,不能将基类对象赋给派生类对错误,不能将基类对象赋给派生类对象象 /b1.Show2(); /错误,不能访问派生类中增加的成员错误,不能访问派生类中增加的成员 /b2-Show2(); /错误,理由同上错误,理由同上 /b3.Show2(); /错误,理由同上错误,理由同上7 7 虚基类虚基类类D类A类A类B

23、类C类D类A类B类C 基类A被一个派生类D多次继承,类D产生两个类A的副本。(virtual) 虚基类的类层次虚基类虚基类的基本思想是:当将一个基类声明为虚基类时,不管它在派生类中被继承多少次,该基类中的成员在该派生类中始终都只有一个拷贝(即所有派生类均共享基类成员)。虚基类通过关键字VirtualVirtual实现。class A private: int x; public: void setx(int a)x=a; void getx()coutxendl;class B:public A ;class C:public A ;class D:public B,public C ;voi

24、d main() D m; m.B:setx(3); m.B:getx(); m.C:setx(4); m.C:getx(); /m.A:setx(5); /会产生冲突会产生冲突 /m.A:getx(); /会产生冲突会产生冲突非非虚虚基基类类继继承承DAABC34class A private: int x; public: void setx(int a)x=a; void getx()coutxendl;class B:virtual public A ; /定义虚基类定义虚基类class C:virtual public A ; /定义虚基类定义虚基类class D:public B,

25、public C ;void main() D m; m.B:setx(3); m.B:getx(); m.C:setx(4); m.C:getx(); m.A:setx(5); m.A:getx(); /不会产生冲突不会产生冲突 m.setx(6); m.getx();虚虚基基类类继继承承DABC3456 派生类调用虚基类的构造函数的方法与调用一般基类的构造函数的方法是不同的。由虚基类经过一次或多次派生出来的派生类,在其每一个派生类的构造函数的成员初始化列表中必须给出对虚基类的构造函数的调用;如果未列出,则调用虚基类缺省的构造函数。在这种情况下,在虚基类的定义中必须有缺省的构造函数。clas

26、s A public: int x; A(int a=0)x=a; class B:virtual public A public: B(int a,int b) :A(b). class C:public virtual A public: C(int a,int b) :A(b). class D:public B,public C public: D(int a,int b,int c,int d,int e) :B(a,b) ,C(c,d) /a . . 由于类A有缺省的构造函数,所以行a可以不列出类A的构造函数调用。但若类A构造函数改为 A(int a)x=a;,则行a编译会出错!此时必须给出对类A的构造函数调用,如:D(int a,int b,int c,int d,int e) :B(a,b) ,C(c,d),A(100) 课后练习:试卷汇编 P17T8 P24T29 P26T10 P33T30 P33T5 P43T10

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

最新文档


当前位置:首页 > 办公文档 > 工作计划

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