您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 其它文档 > 第4章 派生类与继承
1主讲:杨晓花计算机工程系2第4章派生类与继承派生是面向对象程序设计的一个重要特性,它允许在既有类的基础上创建新的类,新类可以从一个或多个既有类中继承函数和数据,而且可以重新定义或加进新的数据和函数,从而形成类的层次和等级。既有类称为基类或父类,在它的基础上建立的新类称为派生类、导出类或子类。4.1派生类的概念4.2派生类对象的创建与撤销4.3虚基类Home34.1派生类的概念一、为什么要使用继承简单的汽车分类层次图:最高层(基类):是最普遍、最一般的。低层(派生类):比它的上一层更具体,并且含有高层的特性(继承),同时也与高层有细微的不同。继承性是程序设计中一个非常有用的、有力的特性,它可以让程序员在既有类的基础上,通过增加少量代码或修改少量代码的方法得到新的类,从而较好地解决了代码重用的问题。汽车运输汽车专用汽车洒水车消防车货车客车BackNext4例:使用继承的必要性person(个人)类classperson{private:charname[10];intage;charsex;public:voidprint();};employee(职工)类classemployee{private:charname[10];intage;charsex;chardepartment[20];//部门floatsalary;//工资public:voidprint();};直接定义employee类,代码重复非常严重。使用继承:将employee说明成person类的派生类。增加新的数据成员department和salary;修改print成员函数。BackNextPrevious5二、派生类的声明一般格式:class派生类名:派生方式基类名{//派生类新增的数据成员和成员函数};如:classemployee:publicperson{chardepartment[20];floatsalary;public://…};BackNextPrevious61.私有派生classemployee:privateperson{//…};基类中的私有成员派生类中无此成员基类中的公有成员派生类中是私有的例4.1例4.2privatepublicafun1()cfun2()基类privatepublic派生类xfun3()yfun4()cfun2()private派生方式BackNextPrevious72.公有派生classemployee:publicperson{//…};基类中的私有成员派生类中无基类中的公有成员派生类中是公有的例4.3privatepublicafun1()cfun2()基类privatepublic派生类xfun3()yfun4()cfun2()public说明:1.在派生类中无法直接使用基类的私有成员。如2.在派生类中声明的名字支持基类中声明的同名的名字。如BackNextPrevious8三、保护成员的作用私有成员在派生类中是无权直接访问的,只能通过调用基类中的公有成员函数的方式实现。如果一定要直接访问基类中的私有成员,可以把这些成员说明为保护成员protected。一般格式:Class类名{[private:]私有成员protected:保护成员public:公有成员};BackNextPrevious91、不涉及派生时,保护成员与私有成员的地位完全一致。例4.4classsamp{inta;protected:intb;public:intc;samp(intn,intm){a=n;b=m;}intgeta(){returna;}intgetb(){returnb;}};voidmain(){sampobj(20,30);obj.a=11;//Error,私有成员obj.b=22;//Error,保护成员obj.c=33;//Okcoutobj.geta()‘‘obj.getb()endl;//Ok}BackNextPreviousabcprotectedprivatepublic102、以公有派生时:基类中的保护成员在派生类中仍是保护的例4.5absetab()protectedpublicbase类protectedpublicsetc()showabc()derive类cprivatesetab()abBackNextPreviousvoidmain(){deriveobj;obj.setab(2,4);obj.setc(3);obj.showabc();}classderive:publicbase{intc;public:voidsetc(intn){c=n;}voidshowabc(){coutaendl;coutbendl;coutcendl;}};classbase{protected:inta,b;public:voidsetab(intn,intm){a=n;b=m;}};obj对象113、以私有派生时:基类中的保护成员在派生类中是私有的。例4.6aseta()protectedpublicbase类protectedpublicsetc()show()derive2类cprivatesetb()bBackPreviousbsetb()protectedpublicderive1类privatevoidmain(){baseop1;op1.seta(1);derive1op2;op2.setb(2);derive2op3;op3.setc(3);op3.show();}aop1对象op3对象seta()op2对象classderive2:publicderive1{intc;public:voidsetc(intsc){c=sc;}voidshow(){couta;//?coutbcendl;}};classbase{protected:inta;public:voidseta(intsa){a=sa;}};classderive1:privatebase{protected:intb;public:voidsetb(intsb){b=sb;}};12类的继承访问特性基类的访问特性类的继承特性子类的访问特性PrivateProtectedPublicPrivateNoaccessPrivatePrivatePrivateProtectedPublicProtectedNoaccessProtectedProtectedPrivateProtectedPublicPublicNoaccessProtectedPublic13分析如下三个类的访问权限,并回答问题。#includeiostream.hclassA{private:inti1;protected:intj1;public:voidf1();A(){i1=10;j1=11;}};classB:publicA{private:inti2;protected:intj2;public:voidf2();B(){i2=20;j2=21;}};classC:publicB{private:inti3;protected:intj3;public:voidf3();C(){i3=30;j3=31;}};voidmain(){Aa;Bb;Cc;//.........}14问题如下:①派生类B中的成员函数f2()能否访问基类A中的成员f1()、i1和j1?②派生类B的对象b能否访问基类A中的成员f1()、i1、j1?③派生类C中的成员函数f3()能否访问基类B中的成员f2()、i2和j2?能否访问间接基类A中的成员f1()、i1和j1?④派生类C的对象c能否访问直接基类B中的成员f2()、i2和j2?能否访问间接基类A中的成员f1()、i1和j1?⑤从如上问题中得出什么结论?解:①可以访问f1()、j1;不可以访问i1。②可以访问f1();不可以访问i1和j1。③可以访问直接基类B中的f2()、j2以及间接基类A中的f1()、j1,不可以访问i2和i1。④可以访问直接基类A中的f2()以及间接基类B中的f1(),其他都不可以访问。⑤在公有继承时,派生类的成员函数可以访问基类中的公有成员和保护成员;派生类的对象仅可以访问基类中的公有成员。15派生类对象的结构//平面坐标点类classPoint2d{public://…对平面坐标点的操作protected:doublex,y;};//三维坐标点类classPoint3d:publicPoint2d{public://…对三维坐标点的操作protected:doublez;};16派生类对象的结构派生类对象中包含一个基类子对象,派生类对象由其基类子对象以及派生类自己的非静态数据成员构成。在派生类中,可以像使用自己的成员一样使用基类的非私有成员。_ZPoint2D_x_yPoint3D17派生类对象的创建和撤销派生类对象的创建1.派生类对象中包含一个基类的子对象,在创建派生类对象时,基类的构造函数也应该被调用,来初始化其中的基类子对象。2.构造函数调用的次序如下:(1)调用基类构造函数(2)子对象类的构造函数(如果有的话)(3)调用派生类的构造函数派生类对象的撤销1.在撤销一个派生类对象时,基类的子对象也被撤销2.析构函数的调用次序和构造函数的调用次序相反18单继承与多继承概念单继承–派生类只从一个基类派生。多继承–派生类从多个基类派生。多重派生–由一个基类派生出多个不同的派生类。多层派生–派生类又作为基类,继续派生新的类。19多继承时派生类的声明class派生类名:继承方式1基类名1,继承方式2基类名2,...{成员声明;}classC:publicA,privateB{//public:}20例4-10:多继承classA{public:voidsetA(intx){a=x;}voidshowA(){};private:inta;};classB{public:voidsetB(intx){b=x;}voidshowB(){}private:intb;};classC:publicA,privateB{public:voidsetC(intx,inty,intz){//直接访问基类的公有成员setA(x);setB(y);c=z;}voidshowC(){}private:intc;};voidmain(){Cobj;obj.setA(5);obj.showA();obj.setC(6,7,9);obj.showC();obj.setB(6);obj.showB();}//错误//错误21说明:多继承派生类构造函数调用的次序如下:(1)调用基类构造函数,调用次序按照它们被继承时说明的次序(从左到右);(2)子对象类的构造函数(按照它们在类中说明的次序);(3)调用派生类的构造函数。22继承时的构造函数—单一继承例4-11派生类名::派生类名(基类所需的形参,本类所需的形参):基类名(参数表){本类成员初始化赋值语句;};C::C(inti,intj):B(i){c=j;coutC'sconstructorcalled.endl;}常规写法如下:23继承时的构造函数—多继承例4-12派生类名::派生类名(基类1形参,基类2形参,...基类n形参,本类形参):基类名1(参数),基类名2(参数),...基类名n(参数){本类成员初始化赋值语句;};C::C(inti,intj,intk):A(i),B(j){c=k;coutC'sconstructorcalled.endl;}常规写法如下:24说明:当不需要参数传递时,派生类构造函数可以不向基类构造函数传递参数。若程序中没有定义无参构造函数,那么调用系统默认的基类构造函数。当基类声明中有带形参的构造函数时,为了使该形参在构造类对象时得到有效的参数值。那么派生类也应声明带形参的构造函数,并将参数
本文标题:第4章 派生类与继承
链接地址:https://www.777doc.com/doc-3967173 .html