2.3继承和派生

上传人:t****d 文档编号:243000846 上传时间:2024-09-13 格式:PPT 页数:56 大小:215KB
返回 下载 相关 举报
2.3继承和派生_第1页
第1页 / 共56页
2.3继承和派生_第2页
第2页 / 共56页
2.3继承和派生_第3页
第3页 / 共56页
点击查看更多>>
资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,56,中北大学计算机系基础教研室,2024/9/13,2006-8 North University of China,C+语言程序设计,3.,类的继承与派生,1,本章主要内容,类的继承与派生,派生类成员的访问属性,派生类的构造函数和析构函数,多重继承,虚基类,3.1类的继承与派生,一、基本概念,1.,派生与继承的意义,继承性,是面向对象程序设计语言的基本特性之一,是指在已有类的基础上建立新的类。,它允许在构造软件系统的层次结构中利用已存在类的部分或全部内容,从而大大提高了软件的重用性。,派生类,它是继承的直接产物,它是通过继承已有类而产生的新类,是代码重用的具体实现。,人,学生,教师,小学生,中学生,大学生,如图:人的分类,农民,工人,一般与特殊的关系,特殊类继承一般类的属性和行为,2.,派生与继承的概念,继承:在定义一个类B时,若它使用了一个已定义类A的部分或全部成员,则称类B继承了类A,并称类 A为基类或父类,称类B为派生类或子类。,派生:在C+语言中,称一个类继承另一个类的过程为派生一个类。,3.,基类和派生类,基类,(,父类,),:,已存在的用来派生新类的类;,派生类,(,子类,),:由已存在的类派生出的新类;,单继承,:从,一个基类,派生的继承;,多继承,:从,多个基类,派生的继承;,基类,派生类,A,B,A,C,B,单继承,多继承,基类与派生类,单继承与多继承,二、派生类的定义格式,class :,;,1.单继承派生类的声明形式:,二、派生类的定义格式(续),2.,继承方式,public,:,公有,继承;,private,:,私有,继承;,protected,:,保护,继承;,作用:控制基类中声明的成员在多大的范围内能被派生类的用户访问;,派生类,私有成员,公有成员,保护成员,私有成员,公有成员,保护成员,基类部分,新定义部分,派生类成员,派生类的构成,三、派生类的构成,构造派生类的过程:,从基类接收成员;,调整从基类接收的成员;,声明派生类的新增成员;,定义派生类的构造函数和析构函数。,三、派生类的构成,(,续,),3.2,派生类成员的,访问属性,公有基类,公有派生类,特点:,基类的公有成员和保护成员作为派生类的成员时,都保持原有的访问属性,而基类的私有成员仍然为基类私有。,公有继承,(public),私有基类,私有派生类,特点:,基类的公有成员和保护成员作为派生类的成员时,都作为派生类的私有成员,且不能被这一派生类的子类访问,而基类的私有成员仍然为基类私有。,不能通过派生类对象引用从私有基类继承过来的任何成员。,3.2,派生类成员的,访问属性,(,续,),私有继承,(private),保护继承,(protected),3.2,派生类成员的,访问属性,(,续,),保护成员:受保护的成员不能被类的外部访问,但可以被派生类成员函数访问,保护继承,保护基类,保护派生类,特点:基类的公有成员和保护成员作为派生类的成员时,都作为派生类的保护成员,而基类的私有成员仍然为基类私有,.,基类的访问特性,类的继承特性,子类的访问特性,Public,Protected,Private,Public,Public,Protected,No access,Public,Protected,Private,Protected,Protected,Protected,No access,Public,Protected,Private,Private,Private,Private,No access,继承对基类成员的访问能力,3.2,派生类成员的,访问属性,(,续,),类,B,为类,A,的直接派生类,类,C,为类,A,的间接派生类;,类,A,是类,B,的直接基类,,是类,C,的间接基类;,类,C,对类,A,的成员的访问属性,由类,A,成员的访问属性、类,B,的继承方式、类,C,的继承方式共同决定。,3.2,派生类成员的,访问属性,(,续,),多级派生的访问属性,类,A,类,B,类,C,例,:,分析下列程序,3.2,派生类成员的,访问属性,(,续,),class Location,public:,void InitL(int xx,int yy);,void Move(int xOff,int yOff);,int GetX() return X;,int GetY() return Y;,private: int X,Y;,;,void Location:InitL(int xx,int yy) X=xx; Y=yy; ,void Location:Move(int xOff,int yOff), X+=xOff; Y+=yOff;,class Rectangle:,public,Location /,公有继承,public:,void InitR(int x,int y,int w,int h);,int GetH() return H;,int GetW() return W;,private:,int H,W;,;,void Rectangle:InitR(int x,int y,int w,int h), InitL(x,y); W=w; H=h; ,#include ,void main(),Rectangle rect;,rect.InitR(2,3,20,10);,rect.Move(3,2);,coutrect.GetX(), rect.GetY(), ,rect.GetH(), rect.GetW()endl;,输出:,5,5,10,20,/,派生类,class V:,public,Rectangle,public:,void Function();,;,void V:Function(),Move(3,2);,公有继承,若继承方式为,private,,,Move(3,2),是否正确?为什么?,若继承方式为,private,,,Move(3,2),仍然,正确,。,原因,:由于类,Rectangle,对类,Location,是公有继承,而类,V,对类,Rectangle,是,直接继承,,因此在类,V,内可以访问基类,Location,的公有成员;,class Rectangle:,private,Location,public:,void InitR(int x,int y,int w,int h);,int GetH() return H;,int GetW() return W;,private: int W,H;,;,void Rectangle:InitR(int x,int y,int w,int h),InitL(x,y);,W=w;,H=h;,私有继承,直接继承,正确,#include ,void main(),Rectangle rect;,rect.InitR(2,3,20,10);,rect.,Move,(3,2);,coutrect.,GetX,(), rect.,GetY,(), ,rect.GetH(), rect.GetW()endl;,错误,/,修改,class Rectangle:private Location,public:,void InitR(int x,int y,int w,int h);,void Move(int xOff,int yOff),Location:Move(xOff,yOff),; ,int GetX() return,Location:GetX(),;,int GetY() return,Location:GetY(),;,int GetH() return H;,int GetW() return W;,private: int W,H;,;,void Rectangle:InitR(int x,int y,int w,int h), InitL(x,y); W=w; H=h; ,通过,成员名限定符,(,:,),指明调用基类中的成员,class V:,public Rectangle,public:,void Function();,;,void V:Function(),Move(3,2);,公有继承,若继承方式为,private,,,Move(3,2),是否正确?为什么?,若继承方式为,private,,,Move(3,2),仍然,错误,。,原因,:由于类,Rectangle,对类,Location,是私有继承,而类,V,对类,Rectangle,是,直接继承,,因此在类,V,内,不,可以访问基类,Location,的公有成员;,错误调用,成员访问权限的控制,例,:,分析下列程序,#include ,class A,public:,void f1();,protected:,int j1;,private:,int i1;,;,class B:public A,public:,void f2();,protected: int j2;,private: int i2;,;,class C:public B, public:,void f3();,;,回答下列问题,并说明原因。,1,、派生类,B,中成员函数,f2(),能否访问基类,A,的成员:,f1(),、,j1,和,i1?,2,、,能否,通过派生类,B,的对象,b,访问基类,A,成员:,f1(),、,j1,和,i1?,可以访问,f1(),和,j1,,,不可以访问,i1,;,可以访问,f1(),,,不可以访问,j1,和,i1,;,3,、派生类,C,的成员函数,f3(),能否访问直接基类,B,的成员,f2(),、,j2,和,i2,?,能否访问间接基类,A,的成员:,f1(),、,j1,和,i1,?,可以访问直接基类中的,f2(),和,j2,以及间接基类中的,f1(),和,j1,,,不可以访问,i2,和,i1,;,4,、,能否,通过派生类,C,对象,c,访问直接基类,B,中的成员:,f2(),、,j2,和,i2?,能否访问间接基类,A,中的成员:,f1(),、,j1,和,i1?,可以访问直接基类中的,f2(),以及间接基类中的,f1(),,,其他都不可以访问;,派生类对象生成时,要调用构造函数进行初始化。编译器的调用过程是先调用基类的构造函数,对派生类中的基类数据进行初始化,然后再调用派生类自己的构造函数,对派生类的数据进行初始化工作。析构函数的调用正好相反。,3.3,派生类的构造函数和析构函数,构造,和析构函数的访问,基类子对象,:派生类的对象中由基类中说明的数据成员和操作所构成的封装体;,基类子对象,由,基类,中的,构造函数,进行,初始化,;,构造函数不能被继承;,派生类构造函数的工作:,对自己的数据成员进行初始化;,负责调用基类构造函数使基类的数据成员得以初始化;,调用子对象的构造函数,对派生类中的子对象进行初始化;,一、派生类的构造函数,派生类构造函数格式:,若某项的,参数表为空,,则该项可从成员初始化列表中省略,表示使用,缺省构造函数,初始化该基类子对象;,(),:(),(),说明,:,#include ,class A,public:,A(int h,int w):he(h),we(w),A(),couthe,we,private: int he, we;,;,class B:public A,public:,B(int h,int w,int h1,int w1,int l):A(h,w),obj1(h1,w1)len=l;,B()coutlenendl;,private: A obj1; int len;,;,void main(),B obj(1,2,3,4,5);,派生类构造函数调用顺序,:,基类的构造函数;,子对象的构造函数;,派生类构造函数体;,二、派生类的析构函数,执行派生类的析构函数时,基类的析构函数也将被调用;,析构函数不能被继承;,析构函数的执行顺序与构造函数严格,相反,;,派生类的析构函数;,基类的析构函数;,例,分析下列程序,#include ,class B,public:,B();,B(int i);,B();,void Print(),const;,private: int b;,;,B:B(), b=0; coutBs default constructor called. endl;,B:B(int i), b=i; coutBs constructor called. endl; ,B:B(), coutBs destructor called. endl; ,void B:Print(),const, coutbendl; ,class C:,public,B,public:,C();,C(int i,int j);,C();,void Print() const;,private: int c;,;,C:C( ), c=0; coutCs default constructor called. endl;,C:C(int i,int j),:B(i), c=j;,coutCs constructor called. endl;,C:C(), coutCs destructor called. endl;,void C:Print(),const,B:Print();,coutcendl;,void main(),C obj(5,6);,obj.Print();,输出:,Bs constructor called.,Cs constructor called.,5,6,Cs destructor called.,Bs destructor called.,三、派生类构造函数使用中应注意的问题,派生类,构造函数的定义中可以,省略,对,基类构造函数,的调用,条件是在基类中必须有,缺省的构造函数,或者,没有定义构造函数,;,当基类的构造函数使用一个或多个参数时,派生类必须定义构造函数,提供将参数传递给基类构造函数的途径;,编译器自动生成缺省构造函数,设,基类,数据成员为,m,个,,派生类,数据成员为,n,个,,派生类的,参数,个数为,x,,,则:,0,x,m+n,;,3.4 多继承的概念,class : , ,;,一、多继承派生类的声明形式:,二、多继承的构造函数,(),:(),(),(),.,多继承构造函数格式:,二、多继承的构造函数,(,续,),派生类构造函数负责所有基类构造函数的调用;,派生类构造函数执行顺序:,执行所有基类的构造函数;,执行所有子对象的构造函数;,执行派生类构造函数体;,处于同一层次的,各基类构造函数的执行顺序,取决于,定义派生类,时指定的各基类,顺序,,与派生类构造函数定义的成员初始化列表中的顺序无关;,例,分析下列程序,#include ,class B1,public:,B1(int i) b1=i; coutConstructor B1. endl; ,void Print() coutb1endl;,private: int b1;,;,class B2, public:,B2(int i) b2=i; coutConstructor B2. endl; ,void Print() coutb2endl;,private: int b2;,;,class B3, public:,B3(int i) b3=i; coutConstructor B3. endl; ,int Getb3() return b3;,private: int b3;,;,class A:,public B2,public B1, public:,A(int i,int j,int k,int l);,void Print();,private: int a; B3 bb;,;,A:A(int i,int j,int k,int l),:B1(i),B2(j),bb(k), a=l;,coutConstructor A. endl; ,/,多继承,,注意顺序,基类构造函数调用顺序与定,义时,继承,顺序不同,/,/,子对象,void A:Print(), B1:Print();,B2:Print();,coutabb.Getb3()endl;,void main(), A aa(1,2,3,4);,aa.Print();,输出,Constructor,B2,.,Constructor,B1,.,Constructor,B3,.,Constructor,A,.,1,2,43,三、二义性问题,1,、产生二义性的原因,在,多继承,情况下,造成的对,基类,中,某个成员,的,访问,出现的,不唯一,的情况;,class A,class C:public A,public B,public:,public:,void f();,void g(),;,;,void h();,class B,;,public:,void f();,void g(),;,;,void f();,c1.f(),A.f(),B.f(),C,三、二义性问题(续),问题:若定义,C c1,;,,,则,c1.f(),是否正确?,答,:,c1.f(),将产生,二义性,;,原因,:,不能识别是调用类,A,或类,B,的,f,函数;,解决方法:,a.,区别出是类,A,或类,B,的,f,函数;,c1.A:f();,或,c1.B:f();,b.,在类中定义同名函数,f,;,当一个,派生类,从,多个基类,派生,而这些基类又有一个,共同的基类,,则对该基类中说明的成员进行访问时,可能会出现二义性;,三、二义性问题(续),class A,class,B2:public A,public:,private:,int a;,int b2;,;,;,class,B1:public A,class C:,public B1,public B2,private:,public:,int b1;,int f();,;,private:,int c;,;,c1.a,A:a,B1:a,C,B2:a,A:a,三、二义性问题(续),问题:若定义,C c1,;,,,则,c1.a,与,c1.A:a,是否正确?,答,:,c1.a,与,c1.A:a,将产生,二义性,;,原因,:,不能识别是通过类,B1,或类,B2,调用类,A,的,a,;,解决方法:,a.,区别出是通过类,B1,或类,B2,调用类,A,的,a,;,c1.B1:a;,或,c1.B2:a;,b.,虚基类;,2,、解决方法,利用成员名限定法消除二义性;,在类中定义一个同名成员;,虚基类;,例,分析下列程序,#include ,class A, public:,A(int i) a=i; coutConstructor A. iendl; ,A() coutDestructor A. endl;,void Print() coutaendl;,private: int a;,;,class,B1:public A, public:,B1(int i,int j):A(i) b1=j;,coutConstructor B1. endl; ,B1() coutDestructor B1. endl;,void Print() A:Print(); coutb1endl; ,private: int b1;,;,class,B2:public A,public:,B2(int i,int j):A(i) b2=j; coutConstructor B2. endl; ,B2() coutDestructor B2. endl;,void Print() A:Print();coutb2endl; ,private: int b2;,;,class,C:public B1,public B2,public:,C(int i,int j,int k,int l,int m):B1(i,j),B2(k,l),c(m), coutConstructor C. endl; ,C() coutDestructor C. endl;,void Print() B1:Print(); B2:Print(); coutcendl; ,private: int c;,;,void main(), C c1(1,2,3,4,5);,c1.Print(); ,a1.a,b1.b1,c1.c,b2.b2,a2.a,Constructor A.,Constructor B1.,Constructor A.,Constructor B2.,Constructor C.,1,2,3,4,5,Destructor C.,Destructor B2.,Destructor A.,Destructor B1.,Destructor A.,注意,基类,A,的实例的数目,如果,a,是类,A,的公有成员,,c1.a,是否正确?,3.5 虚基类,作用:用来解决多继承中可能发生的对同一间接基类继承多次而产生的二义性问题。为最后的派生类提供惟一的基类成员,而不重复继承,注意:在第一级继承时就要将共同基类设计为虚基类,声明格式:,class,派生类名,: virtual, ,例如:,class D:,virtual,public A, private B,virutal,public C,其中:类,A,和类,C,是,虚基类,,而类,B,是,非虚基类,;,class A, public:,void f();,protected: int a;,;,class B:,virtual public A /,虚基类, protected: int b;,;,class C:,virtual public B /,虚基类, protected: int c,;,class D:,public B,public C, public:,int g();,private: int d;,;,下列各语句是否正确?,D n;,n.f();,void D:g(), f( ); ,正确,能够唯一确定调用类,A,的,f(),;,B,D.g(),C,A.f(),虚基类的构造函数,虚基类成员是由最后派生类的构造函数通过调用虚基类的构造函数进行初始化,在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中给出对虚基类的构造函数的调用。如果未列出,则表示调用该虚基类的默认构造函数,在建立对象时,只有最后派生类的构造函数调用虚基类的构造函数,该派生类的其他基类对虚基类构造函数的调用被忽略,#include ,class B0, public:,B0(int n)nV=n;,int nV;,void fun( )coutB0:nV=nVendl;,;,class B1:virtual public B0, public:,B1(int a): B0(a)coutB1:nV=nVendl;,;,class B2:virtual public B0, public:,B2(int a): B0(a)coutB2:nV=nVendl; ,;,class D1: public B1, public B2, public:,D1(int a,int b,int c): B0(a),B1(a),B2(a),coutD1:nV=nVendl; ,void fun(),coutd1:nV=nVendl;,;,void main(),D1 d1(1,2,3);,d1.fun();,d1.B0:fun();,运行结果:,B1:nV=1,B2:nV=1,D1:nV=1,d1:nV=1,B0:nV=1,基类,子对象,数据成员,初始化,虚基类,非虚基类,常数据成员,静态数据成员,一般数据成员,存在多个基类时,执行顺序取决于派生类定义时的顺序,存在多个子对象时,执行顺序取决于类中声明的顺序,成员初始化列表,类外初始化,小结,继承与派生的概念,派生类的定义格式与访问属性,公有,继承、私有继承、保护继承,多级派生的访问属性,派生类的构造函数和析构函数,多继承,概念、构造函数、二义性问题及其解决,虚基类,作用、构造函数,作业与实验,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 大学资料


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!