1、C+大学基础教程大学基础教程第第9 9章章 继承与派生继承与派生北京科技大学北京科技大学-2-第第9 9章章 继承与派生继承与派生9.1 9.1 继承的概念继承的概念 9.2 9.2 继承方式继承方式 9.3 9.3 派生类构造函数的定义派生类构造函数的定义 9.4 9.4 多继承多继承 -3-第第9 9章章 继承与派生继承与派生软件重用软件重用-4-第第9 9章章 继承与派生继承与派生类具有封装性、继承性和多态性类具有封装性、继承性和多态性-5-继承的概念继承的概念自行车自行车-6-继承的概念继承的概念-7-继承的概念继承的概念-8-继承的概念继承的概念-9-Bicycle Mountain
2、BikesRacingBikesTandemBikesis-a relationships继承的概念继承的概念-10-第第9 9章章 继承与派生继承与派生主要介绍:主要介绍:n继承和派生的概念继承和派生的概念n继承方式;继承方式;n派生类的构造函数与析构函数;派生类的构造函数与析构函数;n多继承中的二义性多继承中的二义性n虚基类。虚基类。 -11-9.1 9.1 继承的概念继承的概念 类的继承类的继承是在现有类的基础之上,创建新类的是在现有类的基础之上,创建新类的机制机制。称现有的类为称现有的类为基类基类,新建立的类为新建立的类为派生派生类类。n新类继承了基类的属性和行为新类继承了基类的属性和
3、行为n新类是基类的特殊情况。新类是基类的特殊情况。不必从不必从“草稿草稿”开始创建特殊的程序对象开始创建特殊的程序对象继承是处理继承是处理“特殊情况特殊情况”的面向对象编程机制的面向对象编程机制 -12-派生类的定义格式派生类的定义格式 class class 派生类名:继承方式派生类名:继承方式 基类名基类名 public: public: / /派生类公有成员派生类公有成员 private:private: / /派生类私有成员派生类私有成员 派生类只有派生类只有一个直接基一个直接基类为类为单继承单继承-13-例例: 定义基类定义基类shapeclassclass shapeshape p
4、rivateprivate: : intint m_xm_x, ,m_ym_y; ; /位置位置 charchar m_colorm_color; ; /颜色颜色publicpublic: : voidvoid setpositionsetposition( (intint x x, , intint y y);); voidvoid setcolorsetcolor( (charchar colorcolor);); intint getxgetx();(); intint getygety();(); charchar getcolorgetcolor();();-14-定义派生类定义派生
5、类(等边三角形类等边三角形类)classclass TriangleTriangle: : publicpublic Shape Shape publicpublic: :TriangleTriangle( (intint x x, , intint y y, , charchar colorcolor= =RR, , floatfloat slenslen = 1); = 1);floatfloat GetSideLengthGetSideLength() () constconst; ;voidvoid SetTriangleSetTriangle( (intint x x, , inti
6、nt y y, , charchar colorcolor, , floatfloat slenslen););voidvoid DrawDraw();();privateprivate: :floatfloat m_m_SideLengthSideLength; ;-15-派生新类派生新类: :circle circle 圆形圆形rectangle rectangle 矩形矩形triangle triangle 三角形三角形 基类称为基类称为父类父类派生类称为派生类称为子类子类 shapecirclerectangletriangle-16-派生类的定义格式派生类的定义格式 class cl
7、ass 派生类名:继承方式派生类名:继承方式 基类名基类名1, 1, 继承方式继承方式 基类名基类名n n public: public: / /派生类公有成员派生类公有成员 private:private: / /派生类私有成员派生类私有成员 有多个基类有多个基类派生类有多派生类有多个基类为个基类为多继承多继承-17-例例: :已有基类已有基类base1,base2,base3base1,base2,base3,定义派生类定义派生类deriverderiverclassclass deriverderiver: :publicpublic base1,public base2base1,pu
8、blic base2,private base3private base3 privateprivate: : intint m_m_derdataderdata; ;publicpublic: : voidvoid derfunctionderfunction();();-18-注意注意每一个每一个“继承方式继承方式”,只用于限制对紧随其后,只用于限制对紧随其后之基类的继承。之基类的继承。类的继承方式是派生类对基类成员的继承方式。类的继承方式是派生类对基类成员的继承方式。类的继承方式指定了类外对象对于派生类从基类的继承方式指定了类外对象对于派生类从基类继承来的成员的访问权限。类继承来的成员的
9、访问权限。-19-直接基类和间接基类直接基类和间接基类class baseclass base ; ;class deriver1:public baseclass deriver1:public base ; ;class deriver2:public deriver1class deriver2:public deriver1 父类被称为子类的直接基类直接基类 父类的父类或更高层次的父类被称为这个子类的间接基间接基类类 -20-派生与继承的实例 公司人员管理系统公司人员管理系统: 小型公司人员分为小型公司人员分为: : 经理、兼职技术人员、销售经理和经理、兼职技术人员、销售经理和兼职推销
10、员兼职推销员. .要求要求: :存储所有人员的姓名、编号、级别、当月薪水,计算月薪存储所有人员的姓名、编号、级别、当月薪水,计算月薪总额并显示全部信息。总额并显示全部信息。人员编号在生成人员信息时同时生成,每输入一个人员信人员编号在生成人员信息时同时生成,每输入一个人员信息编号顺序加息编号顺序加1 1。 程序能够对不同人员按不同方法提升级别,月薪的计算程序能够对不同人员按不同方法提升级别,月薪的计算方法是:方法是:n经理拿固定月薪经理拿固定月薪; ;n兼职技术人员按工作小时数领取月薪兼职技术人员按工作小时数领取月薪; ;n兼职推销员的报酬按该推销员当月销售额提成兼职推销员的报酬按该推销员当月销
11、售额提成; ;n销售经理既拿固定月薪也领取销售提成。销售经理既拿固定月薪也领取销售提成。 -21-派生与继承的实例 分析:分析:描述全体职员的共性(基类)描述全体职员的共性(基类)描述每一类特殊人员(派生类)描述每一类特殊人员(派生类) -22-class employeeprotected:char *name;/姓名姓名int individualEmpNo;/个人编号个人编号int grade; /级别级别float accumPay;/月薪总额月薪总额static int employeeNo;/本公司职员编号目前最大值本公司职员编号目前最大值public:employee();/构造
12、函数构造函数employee();/析构函数析构函数void pay(); /计算月薪函数计算月薪函数void promote(int);/升级函数升级函数void displayStatus();/显示人员信息显示人员信息; -23-class technician: public employee/兼职技术人员类兼职技术人员类private: float hourlyRate; / /每小时酬金每小时酬金 int workHours;/当月工作时数当月工作时数public:technician();/构造函数构造函数 void pay(); /计算月薪函数计算月薪函数void displa
13、yStatus();/显示人员信息显示人员信息;新增加的成员新增加的成员同名覆盖,改造基类成员同名覆盖,改造基类成员 派生类的成员派生类的成员: : 1. 1. 从基类继承的成员从基类继承的成员; ; 2. 2. 改造基类成员改造基类成员; ; 3. 3. 添加派生类新成员添加派生类新成员. .-24-9.2 9.2 继承方式继承方式 三种继承方式三种继承方式 publicpublic、protectedprotected、privateprivate 不同继承方式的影响主要体现在:不同继承方式的影响主要体现在: n派生类派生类 成员成员 对基类成员的访问控制。对基类成员的访问控制。 n派生类
14、派生类 对象对象 对基类成员的访问控制。对基类成员的访问控制。定义派生类时要声明继承方式定义派生类时要声明继承方式 -25-9.2.1. 9.2.1. 派生类的定义派生类的定义 派生类的定义形式:派生类的定义形式: class class 派生类名:继承方式派生类名:继承方式 基类基类1, 1, 继承方式继承方式 基类基类2,2, ,继承方式继承方式 基类基类n n 派生类成员声明;派生类成员声明; ;-26-例如例如: : 设已有基类设已有基类base1base1和和base2base2,定义派生类定义派生类deriver.deriver.class deriver: public base
15、1,private base2class deriver: public base1,private base2 private: private: intint newmembernewmember; ; public: public: void void newfunnewfun();();-27-单继承情况,派生类的定义单继承情况,派生类的定义 class class 派生类名:继承方式派生类名:继承方式 基类名基类名 派生类成员声明派生类成员声明 ;-28-例例9.1 9.1 图形类及其派生类的声明图形类及其派生类的声明classclass Shape Shape publicpubl
16、ic: :Shape(Shape(intint x x=0, =0, intint y y=0, =0, charchar c = c = RR););intint GetXGetX() () constconst; ;voidvoid SetXSetX( ( intint x x););intint GetYGetY() () constconst; ;voidvoid SetYSetY( ( intint x x););charchar GetColorGetColor() () constconst; ;voidvoid SetColorSetColor( (charchar c); c
17、);protectedprotected: :charchar m_colorm_color; ;intint m_xm_x; ;intint m_ym_y; ;-29-classclass Circle : Circle : publicpublic Shape Shape publicpublic: :Circle(Circle(intint x x, , intint y y, , floatfloat r=1, r=1, charchar colorcolor= =RR);); float float GetRadiusGetRadius () () constconst; ;void
18、void SetCircleSetCircle( (intint x x, , intint y y, , floatfloat r, r, charchar colorcolor);); void void DrawDraw();();privateprivate: :floatfloat m_Radiusm_Radius; ;-30-classclass TriangleTriangle: : publicpublic Shape Shape publicpublic: :TriangleTriangle( (intint x x, , intint y y, , charchar col
19、orcolor= =RR, , floatfloat slenslen = 1); = 1);floatfloat GetSideLengthGetSideLength() () constconst; ;voidvoid SetTriangleSetTriangle( (intint x x, , intint y y, , charchar colorcolor, , floatfloat slenslen););voidvoid DrawDraw();();privateprivate: :floatfloat m_m_SideLengthSideLength; ;-31-classcl
20、ass RectangleRectangle: : publicpublic Shape Shape publicpublic: :RectangleRectangle( (intint x x, , intint y y, , charchar colorcolor, , intint lengthlength=10, =10, intint widthwidth=10);=10);intint GetWidthGetWidth() () constconst; ;intint GetHeightGetHeight() () constconst; ;voidvoid DrawDraw();
21、();voidvoid SetRectangleSetRectangle ( (intint x x, , intint y y, , charchar colorcolor, , intint lengthlength, , intint widthwidth););privateprivate: :intint m_Widthm_Width; ;intint m_Lengthm_Length; ;-32- 从基类从基类 继承的继承的 成员成员 派生类的成员包括:(派生类的成员包括:(1 1)继承基类的成员,()继承基类的成员,(2 2)派生)派生类定义时声明的成员。类定义时声明的成员。 派
22、生类自己增加的成员,完成两个需求:派生类自己增加的成员,完成两个需求:(1)(1)修改基类修改基类成员,(成员,(2 2)描述新的特征或方法。)描述新的特征或方法。 m_color;m_color;m_x; m_y;m_x; m_y;GetXGetX();();SetXSetX();();GetYGetY();();SetYSetY();();GetColorGetColor();();SetColorSetColor();();m_Radius;m_Radius;GetRadiusGetRadius () () SetCircleSetCircle();();DrawDraw();();m_
23、color;m_color;m_x; m_y;m_x; m_y;GetXGetX();();SetXSetX();();GetYGetY();();SetYSetY();();GetColorGetColor();();SetColorSetColor();();m_m_SideLengthSideLength; ;GetSideLengthGetSideLength(); (); SetTriangleSetTriangle();(); DrawDraw();();m_color;m_color;m_x; m_y;m_x; m_y;GetXGetX();();SetXSetX();();Ge
24、tYGetY();();SetYSetY();();GetColorGetColor();();SetColorSetColor();();m_Width; m_Length;m_Width; m_Length; GetWidthGetWidth(); (); GetHeightGetHeight(); (); DrawDraw();(); SetRectangleSetRectangle();(); 派生类派生类 增加的增加的 成员成员-33-同名覆盖同名覆盖 派生类修改基类的成员,是在派生类中声明了派生类修改基类的成员,是在派生类中声明了一个与基类成员同名的新成员。在派生类作用一个与基类成
25、员同名的新成员。在派生类作用域内或者在类外通过派生类的对象直接使用这域内或者在类外通过派生类的对象直接使用这个成员名,只能访问到派生类中声明的同名新个成员名,只能访问到派生类中声明的同名新成员,这个新成员覆盖了从基类继承的同名成成员,这个新成员覆盖了从基类继承的同名成员,这种情况称为员,这种情况称为同名覆盖同名覆盖。 -34-class Shapeclass Shape public:public: void void DrawDraw();();protectedprotected: : ;classclass TriangleTriangle: : publicpublic Shape S
26、hape publicpublic: :TriangleTriangle( (intint x x, , intint y y, , charchar colorcolor= =RR, , floatfloat slenslen = 1); = 1);floatfloat GetSideLengthGetSideLength() () constconst; ;voidvoid SetTriangleSetTriangle( (intint x x, , intint y y, , charchar colorcolor, , floatfloat slenslen););voidvoid D
27、rawDraw();();privateprivate: :floatfloat m_m_SideLengthSideLength; ;-35-例例9.2 9.2 同名覆盖示例同名覆盖示例 # #includeinclude usingusing namespacenamespace stdstd; ;classclass basebase public public: : voidvoid functionfunction()()coutcoutfunction of class basefunction of class baseendlendl; ; ;classclass derive
28、rderiver: : publicpublic basebase public public: : voidvoid functionfunction()()coutcoutfunction of class function of class deriverderiverendlendl; ; ;-36-voidvoid mainmain()() deriverderiver derobjderobj; ; derobjderobj. .functionfunction();(); 输出结果输出结果: :function of class deriverfunction of class
29、deriver-37-例例9.3 9.3 派生类成员函数对基类同名函派生类成员函数对基类同名函数的改进。数的改进。 /number.hnumber.hclassclass NumberNumber protectedprotected: : intint m_numberm_number; ;publicpublic: : intint GetNumberGetNumber() () returnreturn m_numberm_number; ; voidvoid SetNumberSetNumber( (intint n n) ) m_numberm_number= =n n; voidv
30、oid PrimePrime();();-38-/number.cpp#include#include number.husing namespace std;void Number:Prime()int i;for(i=2; im_number; i+) /找找m_number的因数的因数 if(m_number %i=0)break; if(m_number =i) /判断判断m_number是否被小于是否被小于m_number的数整除的数整除cout m_number is primeendl;elsecout m_number isnt primeendl;-39-/DerNumber
31、.hclass DerNumber: public Numberpublic: void Prime();-40-/DerNumber.cpp#include#include#include number.h#include DerNumber.husing namespace std;void DerNumber:Prime()double sqrtm=sqrt(m_number); /用到用到math.hint i;for(i=2; i=sqrtm; i+)if(m_number %i=0)break; if(sqrtmi)cout m_number is prime.n;else cou
32、t m_number isnt prime.n;-41-/使用模块使用模块#include#include#include number.h#include DerNumber.husing namespace std;void main() Number aNum; DerNumber aDerNum;clock_t start, finish; -42- double elapsed_time1,elapsed_time2;int i;unsigned int max(100000);time( &start );for(i=10000;i=max;i+)aNum.SetNumber(i)
33、;coutaNum.GetNumber() endl;aNum.Prime();time( &finish ); -43- elapsed_time1 = difftime( finish, start );time( &start );for(i=10000;i=max;i+)aDerNum.SetNumber(i);coutaDerNum.GetNumber() endl;aDerNum.Prime();time( &finish ); elapsed_time2 = difftime( finish, start ); -44- coutDelay for using Number cl
34、ass: elapsed_time1 secondsendl;coutDelay for using DerNumber class: elapsed_time2 secondsendl;输出结果输出结果( (部分部分) ):Delay for using Number class: 157 secondsDelay for using Number class: 157 secondsDelay for using Delay for using DerNumberDerNumber class: 151 seconds class: 151 seconds -45-9.2.2. 9.2.2
35、. 继承的访问控制继承的访问控制 派生类继承了基类派生类继承了基类中除构造函数和析中除构造函数和析构函数之外的所有成员构函数之外的所有成员。-46-9.2.2. 9.2.2. 继承的访问控制继承的访问控制 三种继承方式三种继承方式:n公有继承公有继承(public)n私有继承私有继承(private)n保护继承保护继承(protected)-47-9.2.2. 9.2.2. 继承的访问控制继承的访问控制 不同的继承方式使得派生类从基类继承的成员具有不同的继承方式使得派生类从基类继承的成员具有不同的访问控制权限,以实现数据的安全性和共享不同的访问控制权限,以实现数据的安全性和共享性控制。性控制。
36、不同继承方式决定的不同访问控制权限体现在:不同继承方式决定的不同访问控制权限体现在:n派生类的成员函数派生类的成员函数对其继承的基类成员的访问控制;对其继承的基类成员的访问控制;n其它模块通过派生类对象其它模块通过派生类对象对其继承的基类成员的访问控对其继承的基类成员的访问控制。制。-48-1. 1. 公有继承公有继承 公有继承的派生类定义形式:公有继承的派生类定义形式: class class 派生类名:派生类名:publicpublic 基类名基类名 派生类新成员定义;派生类新成员定义; -49-公有继承公有继承 publicpublic是定义公有继承方式的关键字是定义公有继承方式的关键字
37、公有继承方式定义的派生类,继承了基类中公有继承方式定义的派生类,继承了基类中除构造除构造函数和析构函数外函数和析构函数外的其余成员:公有成员、保护成的其余成员:公有成员、保护成员和私有成员员和私有成员被继承的基类成员在派生类中仍将保持其原来的访被继承的基类成员在派生类中仍将保持其原来的访问属性。问属性。派生类的成员函数派生类的成员函数可以访问基类的公有成员和保护可以访问基类的公有成员和保护成员,不能访问基类的私有成员成员,不能访问基类的私有成员; ;派生类以外的其它函数派生类以外的其它函数可以通过派生类的对象,访可以通过派生类的对象,访问从基类继承的公有成员问从基类继承的公有成员, , 但不能
38、访问从基类继承但不能访问从基类继承的保护成员和私有成员。的保护成员和私有成员。 -50-class Point/基类基类Point类的定义类的定义public:/公有函数成员公有函数成员void InitP(float xx=0, float yy=0) X=xx;Y=yy;void Move(float xOff, float yOff) X+=xOff;Y+=yOff;float GetX() return X;float GetY() return Y;private:/私有数据成员私有数据成员float X,Y;-51-class Rectangle: public Point/派生类
39、声明部分派生类声明部分public: /新增公有函数成员新增公有函数成员void InitR(float x, float y, float w, float h) InitP(x,y); /访问基类公有成员函数访问基类公有成员函数 W=w;H=h;float GetH() return H;float GetW() return W;private: /新增私有数据成员新增私有数据成员float W,H;l派生类中的派生类中的 成员函成员函数数 可以直接访问基类可以直接访问基类中的中的publicpublic和和protectedprotected成员成员,但不,但不能访问基类的能访问基类的
40、privateprivate成员。成员。-52-main() Rectangle rect; coutrect.X; /? coutrect.GetX();/?l使用派生类的使用派生类的 对象对象 只能访问基类的只能访问基类的publicpublic成员成员-53-class Rectangle: public Point/派生类声明部分派生类声明部分public:/新增公有函数成员新增公有函数成员void InitR(float x, float y, float w, float h)X=x; Y=y; /?访问基类私有成员访问基类私有成员 W=w;H=h;float GetH() ret
41、urn H;float GetW() return W;private:/新增私有数据成员新增私有数据成员float W,H;l派生类中的派生类中的 成员函成员函数数 可以直接访问基类可以直接访问基类中的中的publicpublic和和protectedprotected成员,成员,但不但不能访问基类的能访问基类的privateprivate成员。成员。-54-class Point/基类基类Point类的定义类的定义public:void InitP(float xx=0, float yy=0) X=xx;Y=yy;void Move(float xOff, float yOff) X+=
42、xOff;Y+=yOff;float GetX() return X;float GetY() return Y;protected:float X,Y;-55-class Rectangle: public Point/派生类声明部分派生类声明部分public:/新增公有函数成员新增公有函数成员void InitR(float x, float y, float w, float h)X=x; Y=y; /?访问基类的保护成员访问基类的保护成员 W=w;H=h;float GetH() return H;float GetW() return W;private:/新增私有数据成员新增私有数
43、据成员float W,H;l派生类中的派生类中的 成员函成员函数数 可以直接访问基类可以直接访问基类中的中的publicpublic和和protectedprotected成员,成员,但不但不能访问基类的能访问基类的privateprivate成员。成员。-56-main() Rectangle rect; coutrect.X; /? coutrect.GetX();/?l使用派生类的使用派生类的 对象对象 只能访问基类的只能访问基类的publicpublic成员成员依然错误依然错误!-57-2.2.私有继承私有继承 私有继承的派生类定义形式:私有继承的派生类定义形式: class clas
44、s 派生类名:派生类名:privateprivate 基类名基类名 派生类新成员定义;派生类新成员定义; -58-私有继承私有继承 privateprivate是定义私有继承方式的关键字是定义私有继承方式的关键字以私有继承方式定义的派生类,继承了基类中可以以私有继承方式定义的派生类,继承了基类中可以继承的成员:公有成员、保护成员和私有成员,这些继承的成员:公有成员、保护成员和私有成员,这些成员在派生类中的访问属性都是私有的。成员在派生类中的访问属性都是私有的。派生类的成员函数派生类的成员函数可以访问基类的公有成员和保护可以访问基类的公有成员和保护成员,不能访问基类的私有成员。成员,不能访问基类
45、的私有成员。派生类以外的其它函数派生类以外的其它函数则不能通过派生类的对象访则不能通过派生类的对象访问从基类继承的任何成员。问从基类继承的任何成员。 -59-class Point/基类声明基类声明public: void InitP(float xx=0, float yy=0) X=xx;Y=yy; void Move(float xOff, float yOff) X+=xOff;Y+=yOff; float GetX() return X; float GetY() return Y;private: float X,Y;-60-class Rectangle: private Poi
46、nt/派生类声明派生类声明public:/新增外部接口新增外部接口void InitR(float x, float y, float w, float h)InitP(x,y);W=w;H=h;/派生类访问基类公有成员派生类访问基类公有成员void Move(float xOff, float yOff) Point:Move(xOff,yOff);float GetX() return Point:GetX();float GetY() return Point:GetY();float GetH() return H;float GetW() return W;private:/新增私有
47、数据新增私有数据float W,H;派生类中的派生类中的 成员函数成员函数 可以直接访问基类中可以直接访问基类中的的publicpublic和和protectedprotected成员,成员,但不能访问基但不能访问基类的类的privateprivate成员。成员。-61-class Rectangle: private Point/派生类声明派生类声明public: /新增外部接口新增外部接口void InitR(float x, float y, float w, float h) X=x; Y=y;/? W=w;H=h; void Move(float xOff, float yOff)
48、Point:Move(xOff,yOff);float GetX() return Point:GetX();float GetY() return Point:GetY();float GetH() return H;float GetW() return W;private: /新增私有数据新增私有数据float W,H;派生类中的派生类中的 成员函数成员函数 可以直接访问基类中的可以直接访问基类中的publicpublic和和protectedprotected成成员,员,但不能访问基类的但不能访问基类的privateprivate成员。成员。-62-class Point/基类声明基类
49、声明public: void InitP(float xx=0, float yy=0) X=xx;Y=yy; void Move(float xOff, float yOff) X+=xOff;Y+=yOff; float GetX() return X; float GetY() return Y;protected: float X,Y;-63-class Rectangle: private Point/派生类声明派生类声明public: /新增外部接口新增外部接口void InitR(float x, float y, float w, float h) X=x; Y=y;/? W=
50、w;H=h; void Move(float xOff, float yOff) Point:Move(xOff,yOff);float GetX() return Point:GetX();float GetY() return Point:GetY();float GetH() return H;float GetW() return W;private: /新增私有数据新增私有数据float W,H;-64-main() Rectangle rect; coutrect.X; /? coutrect.GetX();/?l使用派生类的使用派生类的 对象对象 不能访问基类中的任不能访问基类中
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。