《C继承和派生类.pptx》由会员分享,可在线阅读,更多相关《C继承和派生类.pptx(40页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、类是一种抽象数据类型,是对具有共同属性和行为的对象(事物)的抽象描述。房屋平房楼房办公楼居民楼 顶层的抽象事物具有处于底层的抽象事物的共同特征,而处于底层的抽象事物除了包含顶层抽象事物的特征外,还具有自身的我特征。第1页/共40页 一个类继承另一个类时,这个类被称为继承类、派生类或子类,另一个类被称为被继承类、基类或父类。继承类包含了被继承类中的所有成员,且有自己的成员。继承:从一个或多个先前定义过的类(称为基类)中接受全部或一部分数据(属性)或函数(行为或操作),并且补充定义新的数据或函数,因而形成一个新的低层的类(称为派生类)。而该派生类还可用作更低层派生类的基类。第2页/共40页clas
2、s 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.display;01050第3页/共40
3、页l定义派生类的基本格式:class 派生类名:继承权限 基类名l继承权限:public,protected,private影响的是被继承的原基类成员的访问权限class定义的默认为private,struct定义的默认为public第4页/共40页 继承权限为public时,称该派生为公有派生。基类中的所有public成员在派生类中仍是public成员,所有protected成员在派生类中仍是protected成员。继承权限为private时,称该派生为私有派生。基类中的public成员和protected成员在派生类中均变成private成员。继承权限为protected时,称该派生为保护
4、派生。基类中的public成员和protected成员在派生类中均变成protected成员。第5页/共40页成员成员被其它函数访问被其它函数访问被继承被继承publicpublic可以可以可以可以protectedprotected不可以不可以可以可以privateprivate不可以不可以不可以不可以 无论哪一种继承权限,其基类的private成员均不能为派生类所继承。但可通过被同时继承下来的原基类的某些函数间接访问它们。第6页/共40页private:aa1protected:aa2public:aa3AClass B:public A private:bb1 protected:bb2
5、 public:bb3 private:bb1protected:aa2 bb2public:aa3 bb3B公有派生第7页/共40页private:aa1protected:aa2public:aa3AClass B:protected A private:bb1 protected:bb2 public:bb3 private:bb1protected:aa2 bb2 aa3public:bb3B保护派生第8页/共40页private:aa1protected:aa2public:aa3AClass B:A private:bb1 protected:bb2 public:bb3 priv
6、ate:bb1 aa2 aa3protected:bb2 public:bb3B私有派生第9页/共40页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;第10页/共40
7、页 void print()const /const成员函数:不能改变类中成 员数据的值,也不能调用类中非 const成员函数 cout“name:”name;cout“age:”age;cout“salary:”salaryendl;employee()delete name;Manager:除具有employee的属性外,有新的属性。为避免重复定义,可从employee中派生出manager(派生类)。第11页/共40页class manager:public employee private:int level;public:manager()level=0;manager(char*n
8、ame1,short age1,float salary1,int level1):employee(name1,age1,salary1)level=level1;void print_level()cout“level:”levelendl;派生类构造函数:派生类构造函数:使用初始化符表初始化基类中的成员。使用初始化符表初始化基类中的成员。缺省构造函数缺省构造函数若基类无缺省构造函数,将出错若基类无缺省构造函数,将出错第12页/共40页基类定义部分基类定义部分构造函数构造函数析构函数析构函数printPrint_levelnameagesalarylevel函数函数函数函数函数函数派生类新
9、增部分派生类新增部分公有方法公有方法私有成员私有成员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的一个对象的一个对象,则可访问,则可访问y.ay.a或或y.X:ay.X:a第13页/共40页protected 访问指明符:访问指明符:外部函数不能访问;外部函数不能访问;派生类成员函数可直接访
10、问。派生类成员函数可直接访问。class employee private:short age;float salary;protected:char *name;/;派生类成员函数:派生类成员函数:void manager:print_name()const coutnameendl;外部函数:外部函数:void f()manager m;coutm.nameendl;/错错 第14页/共40页继续派生:class director:public manager /employeedirectormanager多层继承多层继承第15页/共40页class x protected:int i,
11、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;支配规则(就近原则)第16页/共40页class z:public y public:z(int i,int j):y(i,j)/初始化列表初始化列表void print1()cout i=i j=jendl;void print()y:print();void mai
12、n()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=20第17页/共40页 对属于基类的成员进行初始化是通过初始表中的初始化项来初始化的。若初始化表中没有调用基类的初始化项,则自动调用基类的无参构造函数进行初始化。如果派生类的自有成员和继承成员同名,则自有成员优先,即通过这个共同的成员名所访问的是自有成员,而
13、不是继承成员,这种情况下,可以在成员名前加类区分符将同名成员区分开。(支配规则)作用域运算符不能连续使用,即下列形式是不允许的:CName1:Cname2:CName1:Cname2:Cnamen:Cnamen 作用域运算符的左操作数可以是当前对象的直接基类,也可以是当前对象的间接基类(祖先类)。第18页/共40页3 3 多重继承与冲突多重继承与冲突由多个基类派生出一个子类称之为多重继承在多重派生中,如果不同的基类具有名字相同的共有成员或保护成员,此时若在派生类中不正确使用它们,就会产生二义性,这种情况称之为冲突在职研究生研究生教职工第19页/共40页【例】冲突的程序示例。class A pr
14、otected: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;第20页/共40页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;/正确正确(冲突的解决办法冲突的解决办法:在成员名在成员名 前加上基类名前加上基类名
15、)void Sety(int b)y=b;int Gety(void)return y;第21页/共40页void main(void)C c1(10,100);/c1.Show();/冲突冲突 c1.B:Show();/正确正确 类B1类B2类D1类D2类C第22页/共40页class B1 protected:int x;public:void Show()coutx=xn;class B2 protected:int x;public:void Show()coutx=xn;第23页/共40页class D1:public B1 ;class D2:public B2 ;class C:
16、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();/错误,域运算符不能连续使用错误,域运算符不能连续使用 c.SetX2(3);c.D2:Show();/正确,或为正确,或为c.B2:Show(
17、);c.B2:Show();第24页/共40页4 4 构造、析构函数的调用顺序构造、析构函数的调用顺序构造函数的调用顺序只与派生类继承基类的顺序有关,而与初始化成员列表中构造函数顺序无关。一个类的构造函数只能对它的直接基类的构造函数传递实参。编译器调用构造函数的次序:基类 成员对象 派生类编译器调用析构函数的次序:基类 成员对象 派生类第25页/共40页派生类所不能继承的:派生类所不能继承的:友员关系用户定义的赋值运算符析构函数构造函数运算用户定义的 new第26页/共40页5 访问类型的调访问类型的调整整 有时为了某种目的,需要将从派生类继承的内容的访问类型进行调整,这时可以通过访问声明进行
18、。访问声明的一般格式为::;其中,必须基类的public和protected类型的成员名。在访问声明时仅仅说明基类成员名,即对成员数据不可以为它说明数据类型,对成员函数不可以说明参数和返回值类型。第27页/共40页【例】用访问声明调整访问类型class Cbaseint x;protected:int y;public:int Fun(int a,int b)return a;class CDerived:Cbase protected:/int CBase:y;/错误,数据成员的访问声明中不能有类型错误,数据成员的访问声明中不能有类型 CBase:y;/正确正确 public:/int CB
19、ase:Fun(int,int);/错误,成员函数的访问声明不错误,成员函数的访问声明不 能有参数和返回值类型能有参数和返回值类型 CBase:Fun;/正确正确;第28页/共40页 访问声明不允许在派生类中改变基类成员的访问类型,即基类中的protected成员在派生类中只能调整为protected类型,基类中的public成员在派生类中只能调整为public类型。对基类中重载函数进行访问声明,将会调整基类中所有具有该名的函数的访问类型。如果在派生类中有与基类中同名的函数,也允许在派生类中对该函数进行访问声明。第29页/共40页6 6 赋值兼容规则赋值兼容规则 赋值兼容规则是指,在具有继承关
20、系的类之间:1.公有派生类对象可直接赋值给基类的对象2.基类对象不可以赋给派生类对象3.公有派生类对象的地址可赋给基类指针变量4.公有派生类对象可以初始化基类引用5.在将公有派生类的对象赋给基类对象之后,基类对象只能访问派生类中从基类继承的公有成员,不能访问派生类中增加的公有成员。第30页/共40页【例】赋值兼容规则class Cbase protected:int x;public:CBase(int a)x=a;void Show1()coutx=xn;class CDerived:public Cbase protected:int y;public:CDerived(int a,int
21、 b):CBase(b)y=a;void Show1()couty=yn;void Show2()couty=yShow1();/Eb3.Show1();/F/c=b1;/错误,不能将基类对象赋给派生类对象错误,不能将基类对象赋给派生类对象 /b1.Show2();/错误,不能访问派生类中增加的成员错误,不能访问派生类中增加的成员/b2-Show2();/错误,理由同上错误,理由同上 /b3.Show2();/错误,理由同上错误,理由同上第32页/共40页7 7 虚基虚基类类类D类A类A类B类C类D类A类B类C 基类A被一个派生类D多次继承,类D产生两个类A的副本。(virtual)虚基类的类
22、层次第33页/共40页虚基类虚基类的基本思想是:当将一个基类声明为虚基类时,不管它在派生类中被继承多少次,该基类中的成员在该派生类中始终都只有一个拷贝(即所有派生类均共享基类成员)。虚基类通过关键字VirtualVirtual实现。第34页/共40页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 ;void main()D m;m.B:setx(3);m.B:getx();m.C:
23、setx(4);m.C:getx();/m.A:setx(5);/会产生冲突会产生冲突 /m.A:getx();/会产生冲突会产生冲突非非虚虚基基类类继继承承DAABC34第35页/共40页class 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,public C ;void main()D m;m.B:setx(3);m.B:get
24、x();m.C:setx(4);m.C:getx();m.A:setx(5);m.A:getx();/不会产生冲突不会产生冲突 m.setx(6);m.getx();虚虚基基类类继继承承DABC3456第36页/共40页 派生类调用虚基类的构造函数的方法与调用一般基类的构造函数的方法是不同的。由虚基类经过一次或多次派生出来的派生类,在其每一个派生类的构造函数的成员初始化列表中必须给出对虚基类的构造函数的调用;如果未列出,则调用虚基类缺省的构造函数。在这种情况下,在虚基类的定义中必须有缺省的构造函数。第37页/共40页class A public:int x;A(int a=0)x=a;clas
25、s 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)第38页/共40页课后练习:试卷汇编 P17T8 P24T29 P26T10 P33T30 P33T5 P43T10第39页/共40页感谢您的欣赏!第40页/共40页
限制150内