第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说明:当不需要参数传递时,派生类构造函数可以不向基类构造函数传递参数。若程序中没有定义无参构造函数,那么调用系统默认的基类构造函数。当基类声明中有带形参的构造函数时,为了使该形参在构造类对象时得到有效的参数值。那么派生类也应声明带形参的构造函数,并将参数

1 / 39
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功