c学习清华大学五.pptx
1继承与派生的概念 继承就是从一个类中继承它的特性到另一个类中。被继承的类叫做基类,继承基类的类称为派生类。派生类可以继承基类的特性并添加自己的独特特性。第1页/共45页2 继承是自然界的一个普遍的重要特性。派生使新类在继承共性的同时,具有了更加丰富多彩的个性。第2页/共45页3例:定义交通工具类,并从交通工具类派生出小汽车类和卡车类 现实世界的事物多种多样,许多事物都存在着层次关系,这种层次关系使我们找到了描述事物的解决方法。如下图是关于交通工具的一个分类层次关系图。第3页/共45页4类的层次结构图中,下层类是上层类的特殊类;下层类自动具有上层类的特性,同时也具有自身新的特性;越往层次结构图的下层,其特性越具体化这种从上到下的层次结构关系体现了继承与派生的过程;C+面向对象技术也采用了这种继承机制。类的层次结构关系总结第4页/共45页5派生类派生类是在基类的基础上产生的特殊类,派生类自动继承了基类的成员;派生类具有自身的属性和行为,不然就完全等同于基类,这样就没有必要派生新类;继承是为了避免代码的重复;派生是为了使新产生的派生类除具有基类的共性之外,还具有其他个性。第5页/共45页6单继承的定义格式为:单继承的定义格式为:classclass 派生类名派生类名:继承方式继承方式 基类名基类名 派生类新定义成员派生类新定义成员;1.1.派生类的定义格式派生类的定义格式public:公有派生private:私有派生protected:保护派生规定基类成员在派生类中的访问权限缺省情况下表示private方式。第6页/共45页7class Student public:void display();private:int num;char name10;char sex;基类定义第7页/共45页8class Student1:public Student public:void display()/改造的成员函数改造的成员函数 coutage:ageendl;coutaddress:addrendl;private:int age;/新新增增加加的的数数据据成成员员 char addr30;/新新增增加加的的数数据据成员成员;派生类的定义派生类的定义第8页/共45页9派生类的生成过程经历了三个步骤:吸收基类成员改造基类成员添加派生类新成员2.派生类的生成过程 第9页/共45页10(1)吸收基类成员在C+的继承机制中,派生类吸收基类中除构造函数和析构函数之外的全部成员。吸收基类成员是一个重用的过程,体现了代码的重用第10页/共45页11(2)改造基类成员 由于基类的部分成员在派生类中可能不需要却也被继承下来,对这些没有实际需要而被继承的成员,在派生类中需要对其进行改造。改造基类成员包括两个方面:(1)通过派生的三种继承方式来控制;(2)通过在派生类中定义同名成员(包括成员函数和数据成员)来屏蔽在派生类中不起作用的部分基类成员。第11页/共45页12(3)添加新成员添加派生类的新成员是继承机制的核心内容。仅仅继承基类的成员是不够的,需要在派生类中添加新成员,以保证派生类自身特殊属性和行为的实现。第12页/共45页136.3 访问权限控制 根据派生类的定义格式可知,有三种继承方式。publicprotectedprivate第13页/共45页14派生类成员的访问属性派生类成员的访问属性派生类成员的访问属性派生类成员的访问属性由一个类生成的对象,它只能访问类的公有成员,不能访问其它成员:而一个类的成员函数可以访问类中所有成员!第14页/共45页15当类的继承方式为public(公有)继承属性时,在派生类中,基类的公有成员和保护成员被继承后其访问属性没有变化,即分别作为派生类的公有成员和保护成员,派生类的成员可以直接访问它们。但是,在公有继承时派生类的成员无法访问基类的私有成员。1.公有继承第15页/共45页16公有继承公有继承公有继承时,派生类的对象只可访问基类中的公有成员,不能访问其它成员。派生类的成员函数可以访问基类中的公有成员派生类的成员函数可以访问基类中的公有成员和保护成员,不可访问其私有成员和保护成员,不可访问其私有成员。特别提示第16页/共45页17公有继承公有继承第17页/共45页18classstudentprivate:intage;protected:charsex;public:intGetage();classgraduatestudent:publicstudentprivate:intstunum;public:intGetnum();公有继承特点:基类的公有成员和保护成员作为派生类的成员时,都保持原有状态,而私有成员仍是私有。第18页/共45页19voidgraduatestudent:Getnum()/voidgraduatestudent:Getnum()/派生类成员函数定义派生类成员函数定义/coutage:ageendl;/coutage:ageendl;/不可访问基类的私有成员不可访问基类的私有成员 coutstunum:stunumendl;/coutstunum:stunumendl;/派生类的私有成员派生类的私有成员 coutage:Getage()endl;/coutage:Getage()endl;/基类的公有成员基类的公有成员 coutsex:sexendl;coutsex:sexendl;/即:即:student:sexstudent:sex 基类的保护成员基类的保护成员 即:即:student:Getage()student:Getage()公有继承第19页/共45页20voidmain()voidmain()graduatestudentzh;/graduatestudentzh;/生成派生类对象生成派生类对象();/();/即:即:student:Getage();student:Getage();基类中的公有成员基类中的公有成员();/();/访问派生类中的公有成员访问派生类中的公有成员/coutcout;/;/即:即:即:即:student:sexstudent:sex,errorerror私有成员私有成员私有成员私有成员/coutcout;/;/errorerror私私有成员有成员有成员有成员/coutcout;/;/即:即:即:即:student:agestudent:age,errorerror保护成员保护成员保护成员保护成员 公有继承第20页/共45页21在派生类中,基类的公有成员和保护成员作为派生类的私有成员,派生类的成员可以直接访问它们,而派生类的成员无法访问基类的私有成员;在派生类的外部,派生类的成员和派生类的对象均无法访问基类的全部成员;私有继承之后,全部基类成员在派生类中都成为了私有成员或不可访问的成员,无法进一步派生;私有继承方式一般很少使用。2.私有继承 第21页/共45页22私有继承时,基类的成员只能由直接派生类访问,而无法再往下继承。特别提示私有继承私有继承第22页/共45页232。私有继承第23页/共45页24特点:基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。2 私有继承classstudentprivate:intage;protected:charsex;public:intGetage();classgraduatestudent:privatestudentprivate:intstunum;public:intGetnum();第24页/共45页25voidgraduatestudent:Getnum()/voidgraduatestudent:Getnum()/派生类成员函数定义派生类成员函数定义/coutage:ageendl;/coutage:ageendl;/不可访问基类的私有成员不可访问基类的私有成员 coutstunum:stunumendl;/coutstunum:stunumendl;/派生类的私有成员派生类的私有成员 coutage:Getage()endl;/coutage:Getage()endl;/基类的公有成员基类的公有成员 coutsex:sexendl;coutsex:sexendl;/即:即:student:sexstudent:sex 基类的保护成员基类的保护成员 2 私有继承第25页/共45页26voidmain()voidmain()graduatestudentzh;/graduatestudentzh;/生成派生类对象生成派生类对象/();/();/即:即:student:Getage();student:Getage();不能不能访问访问();/();/访问派生类中的公有成员访问派生类中的公有成员/coutcout;/;/即:即:即:即:student:sexstudent:sex,errorerror私有成员私有成员私有成员私有成员/coutcout;/;/errorerror私有成员私有成员私有成员私有成员/coutcout;/;/即:即:即:即:student:agestudent:age,errorerror 2 私有继承第26页/共45页273.保护继承当类的继承方式为protected继承属性时,在派生类中,基类的公有成员和保护成员均作为派生类的保护成员,派生类的成员可以直接访问它们,而派生类的成员无法访问基类的私有成员。在派生类的外部,派生类的成员和派生类的对象均无法访问基类的全部成员。如果基类只进行了一次派生,则保护继承和私有继承的功能完全相同,但保护继承可以进一步派生,而私有继承则不可以,两者具有实质性差别。第27页/共45页28第28页/共45页29 基类的所有公有成员和保护成员都作为派生类的保护成员,并且只能被它的派生类成员函数访问,基类的私有成员仍是私有的。保护继承保护继承classstudentprivate:intage;protected:charsex;public:intGetage();classgraduatestudent:protectedstudentprivate:intstunum;public:intGetnum();第29页/共45页30voidgraduatestudent:Getnum()/voidgraduatestudent:Getnum()/派生类成员函数定义派生类成员函数定义/coutage:ageendl;/coutage:ageendl;/不可访问基类的私有成员不可访问基类的私有成员coutstunum:stunumendl;/coutstunum:stunumendl;/派生类的私有成员派生类的私有成员coutage:Getage()endl;/coutage:Getage()endl;/基类的公有成员基类的公有成员coutsex:sexendl;coutsex:sexendl;/即:即:student:sexstudent:sex 基类的保护成员基类的保护成员 1.3保护继承保护继承第30页/共45页31voidmain()graduatestudentzh;/生成派生类对象/();/即:student:Getage();不能访问();/访问派生类中的公开成员/cout;/即:即:student:sex,error私有成员私有成员/cout;/error私有成员私有成员/cout;/即:即:student:age,error1.3保护继承保护继承第31页/共45页32三种继承方式的属性表 公有成员私有成员保护成员公有继承公有不可访问保护私有继承私有不可访问私有保护继承保护不可访问保护第32页/共45页33基类的构造函数的功能是创建基类对象并进行初始化,而析构函数的功能在基类对象生存期结束时对基类对象进行必要的清理工作。在派生类的生成过程中,派生类将产生新的成员,对新增数据成员的初始化需要由派生类自身的构造函数完成,而对派生类对象的清理工作需要由相应的析构函数完成。7.4 派生类的构造函数和析构函数 第33页/共45页34派生类的数据成员既包括基类的数据成员,也包括派生类新增数据成员。派生类构造函数在对派生类对象进行初始化时需要对基类数据成员、新增数据成员和内嵌对象成员进行初始化。在定义派生类的构造函数时除了对自己的数据成员进行初始化外,还必须调用基类的构造函数初始化基类的数据成员1.派生类的构造函数 第34页/共45页35派生类构造函数的格式:派生类名:派生类名(总参数表):基类名(参数表1),对象成员名(参数表2)派生类新增成员的初始化;第35页/共45页36派生类构造函数的调用顺序如下:基类的构造函数对象成员类的构造函数(若有)派生类构造函数注意:1、若基类中未定义带参数构造函数,则派生类构造函数的定义中可以省略对基类构造函数的调用。2、若基类的构造函数使用了参数,则派生类必须定义构造函数,为基类构造函数提供参数。第36页/共45页37#include class Basepublic:Base()coutBase Constructorendl;class DeriveA:public Basepublic:DeriveA()coutDeriveA Constructorendl;class DeriveB:public DeriveApublic:DeriveB()coutDeriveB Constructorendl;void main()DeriveB B;第37页/共45页38#includeclass Baseprivate:int n;double a;public:Base(int x1,double x2)n=x1;a=x2;coutCall A Destructorendl;coutn=nendl;couta=aendl;Base();第38页/共45页39class Derive:public Baseprivate:int m;double b;public:Derive(int x1=10,double x2=20,int y1=218,double y2=288.8):Base(x1,x2),m(y1),b(y2)coutCall B Destructorendl;coutm=mendl;coutb=bendl;Derive();void main()Derive obj1;第39页/共45页40classdataintx;public:data(intx)data:x=x;coutclassdatan;classAdatad1;public:A(intx):d1(x)coutclassAn;运行结果:classdataclassAclassdataclassBclassCclassB:publicAdatad2;public:B(intx):A(x),d2(x)coutclassBn;classC:publicBpublic:C(intx):B(x)coutclassCn;voidmain()Cobject(5);派生类的构造函数派生类的构造函数第40页/共45页41析析构构函函数数也也不不能能被被继继承承,因此在执行派生类的析构函数时,基类的析构函数也将被调用。析构函数调用的顺序与构造函数相反.2派生类的析构函数派生类的析构函数classMpublic:M()m1=m2=0;M(inti,intj)m1=i;m2=j;voidprint()coutm1,m2,;M()coutMsdestructorcalled.n;private:intm1,m2;第41页/共45页42classN:publicMclassN:publicM public:public:N()n=0;N()n=0;N(inti,intj,intk);N(inti,intj,intk);voidprint()M:print();coutnendl;N()coutNsdestructorcalled.n;private:intn;5,6,75,6,7-2,-3,-4-2,-3,-4Nsdestructorcalled.Msdestructorcalled.Nsdestructorcalled.Msdestructorcalled.N:N(inti,intj,intk):M(i,j),n(k)voidmain()N n1(5,6,7),n2(-2,-3,-4);n1.print();n2.print();第42页/共45页43#includeclass BaseAint x;public:BaseA(int i)x=i;coutConstructing of BaseAendl;BaseA()coutDestructing of BaseAendl;void display()coutx=xendl;第43页/共45页44class DerivedB:public BaseABaseA d;public:DerivedB(int i):BaseA(i),d(i)coutConstructing of DerivedBendl;DerivedB()coutDestructing of DerivedBendl;void main()DerivedB obj(10);();第44页/共45页45感谢您的观看!第45页/共45页