收藏 分销(赏)

第八章-继承与派生PPT课件.ppt

上传人:可**** 文档编号:777547 上传时间:2024-03-13 格式:PPT 页数:64 大小:1,003.50KB
下载 相关 举报
第八章-继承与派生PPT课件.ppt_第1页
第1页 / 共64页
第八章-继承与派生PPT课件.ppt_第2页
第2页 / 共64页
第八章-继承与派生PPT课件.ppt_第3页
第3页 / 共64页
第八章-继承与派生PPT课件.ppt_第4页
第4页 / 共64页
第八章-继承与派生PPT课件.ppt_第5页
第5页 / 共64页
点击查看更多>>
资源描述

1、2024/3/13周三可编辑1C+高级语言程序设计高级语言程序设计第8章 继承与派生 第第8 8章章 继承与派生继承与派生8.1 继承的概念8.2 定义基类和派生类8.3 构造函数和析构函数8.4 转换与继承2回顾回顾上章:类对象本章:继承的概念和分类;继承的用法:如何继承某个祖先类的功能,如何为后代类添加新的功能。32024/3/13周三可编辑-4-8 8.1 1 继承的概念继承的概念 自行车 Bicycle自行车自行车8.1 8.1 继承的概念继承的概念-例子例子5双人自行车 Tandem Bike8.1 8.1 继承的概念继承的概念-例子例子6竞速自行车 Racing Bike8.1 8

2、.1 继承的概念继承的概念-例子例子78.1 8.1 继承的概念继承的概念-例子例子山地车 Mountain Bike88.1 8.1 继承的概念继承的概念-例子例子山地车继承了自行车的特征山地车“派生”于 自行车98.1 8.1 继承的概念继承的概念类的继承是在现有类的基础之上,创建新类的机制。称现有的类为基类,新建立的类为派生类。Bike基类Tandem Bike派生类派生于int Wheel;bool Run();int Wheel;bool Run();int Seat;父类子类 从基类 继承102024/3/13周三可编辑-11-8 8.2 2 定义基类和派生类定义基类和派生类 8.

3、2 8.2 定义基类和派生类定义基类和派生类定义派生类时要声明继承方式 访问控制受继承方式的影响继承导致一种特殊的语法现象:同名覆盖三种继承方式 public、protected、private 不同继承方式的影响主要体现在:派生类 成员 对基类成员的访问控制 派生类 对象 对基类成员的访问控制122024/3/13周三可编辑-13-8.2.1 8.2.1 简单的继承和派生简单的继承和派生例例8-8-1 1 简单的继承和派生简单的继承和派生问题:想在屏幕上画出正三角形、矩形或圆形方法一:结构化方法DrawTri (int x,int y,char color,int side);DrawRec

4、t (int x,int y,char color,int length,int width)DrawCircle(int x,int y,char color,int Radius)方法二:面向对象?class circle 圆形class rectangle 矩形class triangle 三角形基类:class shape色彩 color位置(x,y)shapecirclerectangletriangle14classTshapeprivate:uint_x,_y;/几何形状的位置public:TShape();uintgetX();uintgetY();voidsetX(uintx

5、);voidsetY(uinty);voidDraw();成员函数的分类1、构造函数2、设置属性值3、读取属性值15/TShape01.cpp:类TShape的实现#includeTShape01.h#includeusingnamespacestd;TShape:TShape()_x=10;_y=10;voidTShape:Draw()coutThisisTShape:Draw()endl;成员函数的分类1.构造函数2.设置属性值3.读取属性值4.执行16#includeTShape01.hclassTEllipse:publicTShapepublic:voidDraw();17/TEll

6、ipse01.cpp:类TEllipse的实现#includeTEllipse01.h#includeusingnamespacestd;voidTEllipse:Draw()coutDrawanellipsewithcolorendl;182024/3/13周三可编辑-19-8.2.2 8.2.2 定义派生类定义派生类8.2.2 8.2.2 定义派生类定义派生类class 派生类名:继承方式 基类1,继承方式 基类2,继承方式 基类n 派生类成员声明;;例如:已有基类b1和b2,定义派生类derive,其中包括私有整型成员 newInt,公有函数成员 int newFun(),私有函数成员

7、int max(int a,int b);写出类derive的定义classderive:publicb1,privateb2private:intnewInt;public:voidnewFun();private:intmax(inta,intb);202024/3/13周三可编辑-21-8.2.3 8.2.3 访问控制和继承关系访问控制和继承关系8.2.3 8.2.3 访问控制和继承关系访问控制和继承关系类成员的可见性公有成员:public保护成员:protected私有成员:private继承的方式公有继承(public)保护继承(protected)私有继承(private)派生类继

8、承了基类中的所有成员,但不包括构造函数析构函数228.2.3 8.2.3 访问控制和继承关系访问控制和继承关系不同继承方式决定的不同访问控制权限体现在:派生类的成员函数对其继承的基类成员的访问控制;其它模块通过派生类对象对其继承的基类成员的访问控制。private:protected:public:基类?派生类publicprotectedprivate继承方式决定继承成员的访问权限继承来的成员的访问权限?231.1.公有继承公有继承 公有继承的派生类定义形式:class 派生类名:public 基类名派生类新成员定义;;private:private:protected:protected:

9、public:public:基类基类?派生类派生类1.1.基类成员基类成员 在派生类中的访问属性不变;2.2.派生类的成员函数派生类的成员函数 可以访问基类的公有成员和保护成员,不能访问基类的私有成员;3.3.派生类以外的其它函数派生类以外的其它函数 可以通过派生类的对象,访问从基类继承的公有成员,但不能访问从基类继承的保护成员和私有成员。privateprivateprotectedprotectedpublicpublic派生类成员派生类成员函数可以访问函数可以访问派生类对象派生类对象基类基类成员的成员的属性属性public24classPoint/基类public:voidInitP(f

10、loatxx=0,floatyy=0)X=xx;Y=yy;voidMove(floatxOff,floatyOff)X+=xOff;Y+=yOff;floatGetX()returnX;floatGetY()returnY;private:floatX,Y;classRectangle:publicPoint/派生类public:/新增公有函数成员voidInitR(floatx,floaty,floatw,floath)InitP(x,y);/访问基类公有函数W=w;H=h;floatGetH()returnH;floatGetW()returnW;private:/新增私有数据成员floa

11、tW,H;int main()Rectangle rect;coutrect.X;/可否?可否?coutrect.GetX();/可否?可否?return 0;此语句可否改为:X=x;Y=y;派生类中的派生类中的 成员函数成员函数 可以直接访问可以直接访问基类中的基类中的publicpublic和和protectedprotected成员成员,但不能访问基类的但不能访问基类的privateprivate成员。成员。25classPointpublic:voidInitP(floatxx=0,floatyy=0)X=xx;Y=yy;voidMove(floatxOff,floatyOff)X+=

12、xOff;Y+=yOff;floatGetX()returnX;floatGetY()returnY;private:floatX,Y;classRect:publicPointpublic:/新增公有函数成员Rect(floatx,floaty,floatw,floath)X=x;Y=y;W=w;H=h;floatGetH()returnH;floatGetW()returnW;private:/新增私有数据成员floatW,H;1.int main()2.Rect r(1,2,3,4);3.coutr.X;4.coutr.GetX();5.return 06.A.public:B.priv

13、ate:C.protected:D.什么都不填?此处填啥,才能让编译器只对第3行代码报错?262.2.私有继承私有继承 私有继承的派生类定义形式:class 派生类名:private 基类名派生类新成员定义;;private:private:protected:protected:public:public:基类基类?派生类派生类1.1.基类成员基类成员 在派生类中的访问属性都变成在派生类中的访问属性都变成 privateprivate;2.2.派生类的成员函数派生类的成员函数 可以访问基类的公有成员和保护成员,不能访问基类的私有成员;3.3.派生类以外的其它函数派生类以外的其它函数 不能通过

14、派生类的对象,访问从基类继承的不能通过派生类的对象,访问从基类继承的任何成员。任何成员。privateprivateprivateprivateprivateprivate派生类成员派生类成员函数可以访问函数可以访问基类基类成员的成员的属性属性private派生类对象派生类对象273.3.保护继承保护继承 私有继承的派生类定义形式:class 派生类名:protected 基类名派生类新成员定义;;private:private:protected:protected:public:public:基类基类?派生类派生类1.1.基类成员基类成员 公有成员和保护成员在派生类中变成保护类型的,基类的

15、私公有成员和保护成员在派生类中变成保护类型的,基类的私 有成员属性不变;有成员属性不变;2.2.派生类的成员函数派生类的成员函数 可以访问基类的公有成员和保护成员,不能访问基类的私有成员;3.3.派生类以外的其它函数派生类以外的其它函数 不能通过派生类的对象,访问从基类继承的不能通过派生类的对象,访问从基类继承的任何成员。任何成员。privateprivateprotectedprotectedprotectedprotected派生类成员派生类成员函数可以访问函数可以访问基类基类成员的成员的属性属性protected派生类对象派生类对象28私有继承和保护继承的区别私有继承和保护继承的区别pr

16、ivate:protected:public:父类privateprotectedprotected子类protectedprivate:protected:public:父类privateprivateprivate:子类privateprivateprivateprivate:孙类privateprotectedpublic孙类成员函数无法访问孙类成员函数无法访问protectedpublicprivateprotectedprotected孙类孙类成员函数可以访问孙类成员函数可以访问29继承方式影响访问控制继承方式影响访问控制public:protected:private:public

17、publicprotectedprivateprotectedprotectedprotectedprivateprivateprivateprivateprivate基类存取方式继承类型派生类继承的基类成员的访问属性302024/3/13周三可编辑-31-8.2.4 8.2.4 同名覆盖同名覆盖8.2.4 8.2.4 同名覆盖同名覆盖 override override class base public:void f()coutbaseendl;class deriver:public base public:void f()coutderiverendl;int main()derive

18、r derobj;derobj.f();return 0;输出结果输出结果?A:base B:deriver在在派生类中声明了一个中声明了一个与基类成员同名的新成员的新成员O Ov ve er rR Ri id de e只能访问到派生类只能访问到派生类中的同名新成中的同名新成员员在派生类作用域内派生类作用域内或者在类外类外通过派生类的对象直接使用这个成员名32classShapepublic:void Draw();protected:;classTriangle:publicShapepublic:Triangle(intx,inty,charcolor=R,floatslen=1);flo

19、atGetSideLength()const;voidSetTriangle(intx,inty,charcolor,floatslen);void Draw();private:floatm_SideLength;图形类中的同名覆盖332024/3/13周三可编辑-34-8.3 8.3 构造函数和析构函数构造函数和析构函数8 8.3.3 构造函数与析构函数构造函数与析构函数 基类的构造函数和析构函数不能被派生类所继承派生类一般需要定义自己的构造函数和析构函数派生类的构造及析构函数通常会受到基类构造及析构函数的影响352024/3/13周三可编辑-36-8.3.1 8.3.1 基类只有无参数构

20、造函数基类只有无参数构造函数8.3.1 8.3.1 基类只有无参数的构造函数基类只有无参数的构造函数在基类具有无参构造函数,派生类又没有定义构造函数的时候,系统会自动的调用基类无参构造函数,来构造派生类对象中的基类成分。如果基类没有无参构造函数,派生类也不定义自己的构造函数,在编译的时候,一定会有语法错误。372024/3/13周三可编辑-38-8.3.2 8.3.2 派生类的构造函数派生类的构造函数8 8.3.3.2.2 派生类的构造函数派生类的构造函数不参与继承的特殊函数构造函数析构函数作为特权地位的友元函数赋值运算符函数派生类需要自己定义的构造函数和析构函数。398 8.3.3.2.2

21、派生类的构造函数派生类的构造函数派生类名:派生类名(基类所需形参,本类成员所需形参):基类1(基类参数表1),基类n(基类参数表n),对象成员1(对象参数表1),对象成员m(对象参数表m)本类基本类型数据成员初始化;初始化列表40/TShape04.cpp#includeTShape04.h#includeTShape:TShape(uintx,uinty)_x=x;_y=y;voidTShape:Draw()std:coutThisisTShape:Draw()std:endl;voidTShape:getXY(uint&x,uint&y)x=_x;y=_y;voidTShape:getRG

22、B(uchar&R,uchar&G,uchar&B)R=_RED;G=_GREEN;B=_BLUE;/TShape04.htypedefunsignedintuint;typedefunsignedcharuchar;classTShapeprivate:uint_x,_y;/几何形状的位置protected:/*声明几何形状的颜色。允许TShape的派生类直接访问这些颜色属性,*而不允许在类外通过类的对象直接访问这些属性*/uchar _RED,_GREEN,_BLUE;public:TShape(uintx,uinty);voidgetXY(uint&x,uint&y);voidsetXY

23、(uintx,uinty);voidDraw();voidgetRGB(uchar&R,uchar&G,uchar&B);voidsetRGB(ucharR,ucharG,ucharB);例8-4 单继承派生类构造函数41/TEllipse04.cpp#includeTEllipse04.h#includeTEllipse:TEllipse(uintlongR,uintshortR,uintx,uinty):TShape(x,y)_longR=longR;_shortR=shortR;_RED =0 x00;/在派生类构造函数中初始化基类保护成员 _GREEN=0 x00;_BLUE =0 x

24、00;TEllipse:TEllipse()voidTEllipse:Draw()uintx,y;getXY(x,y);/调用基类函数获取椭圆的圆心坐标std:coutDrawanellipsewithcolor(;std:coutstatic_cast(_RED),static_cast(_GREEN),static_cast(_BLUE)atpoint(;/std:cout_x“,”_y“)”std:endl;/错误!在派生类中不能访问基类私有成员std:coutx,y)std:endl;/TEllipse04.h#includeTShape04.hclassTEllipse:public

25、TShapeprotected:uint_longR,_shortR;public:TEllipse(uintlongR,uintshortR,uintx,uinty);TEllipse();voidDraw();voidgetR(uint&longR,uint&shortR);voidsetR(uintlongR,uintshortR);例8-4 单继承派生类构造函数42例8-4 单继承派生类构造函数432024/3/13周三可编辑-44-8.3.3 8.3.3 包含内嵌对象的派生类构包含内嵌对象的派生类构造函数造函数派生类名:派生类名(基类所需形参,本类成员所需形参):基类1(基类参数表1

26、),基类n(基类参数表n),对象成员1(对象参数表1),对象成员m(对象参数表m)本类基本类型数据成员初始化;初始化列表45/TShape05.h#pragmaonce#includeGlobalType05.h#includeTColor05.hclassTshapeprivate:uint_x,_y;/几何形状的位置protected:TColor_color;/颜色public:TShape(uintx,uinty);TShape(uintx,uinty,TColorcolor);TShape();voidgetXY(uint&x,uint&y)const;voidsetXY(uintx

27、,uinty);voidDraw();TColorgetColor()const;voidsetColor(TColorcolor);/GlobalType05.h#pragmaonce/预处理指令,避免重复包含本头文件typedefunsignedintuint;typedefunsignedcharuchar;/TColor05.h#pragmaonce#includeGlobalType05.henumEColorComponentRED,GREEN,BLUE;classTColorprivate:uchar_RED,_GREEN,_BLUE;public:TColor(constuch

28、arR=0 x00,constucharG=0 x00,constucharB=0 x00);/普通构造函数TColor(constTColor&color);/拷贝构造函数TColor&operator=(constTColor&color);/重载赋值运算符voidsetColor(ucharR,ucharG,ucharB);uchargetComponent(EColorComponentcomponent)const;例8-5 派生类的构造函数46/TColor05.cpp#includeTColor05.hTColor:TColor(ucharR/*=0 x00*/,ucharG/*

29、=0 x00*/,ucharB/*=0 x00*/)_RED=R;_GREEN=G;_BLUE=B;/普通构造函数TColor:TColor(constTColor&color)_RED=color._RED;_GREEN=color._GREEN;_BLUE=color._BLUE;/拷贝构造函数voidTColor:setColor(ucharR,ucharG,ucharB)_RED=R;_GREEN=G;_BLUE=B;/TEllipse.h#pragmaonce#includeTShape05.h#includeGlobalType05.hclassTEllipse:publicTSh

30、apeprotected:uint_longR,_shortR;public:TEllipse(uintlongR,uintshortR,uintx,uinty,TColorcolor);TEllipse(uintlongR,uintshortR,uintx,uinty);TEllipse();voidDraw();voidgetR(uint&longR,uint&shortR)const;voidsetR(uintlongR,uintshortR);例8-5 派生类的构造函数47例8-5 派生类的构造函数48/TShape06.h#pragmaonce#includeGlobalType06

31、.h#includeTColor06.hclassTShapeprivate:uint_x,_y;/几何形状的位置protected:TColor_color;/颜色public:/TShape(uintx,uinty);TShape(uint x=0u,uint y=0u);/默认构造函数TShape(uintx,uinty,TColorcolor);TShape();voidgetXY(uint&x,uint&y)const;voidsetXY(uintx,uinty);voidDraw();TColorgetColor()const;voidsetColor(TColorcolor);/

32、TEllipse06.cpp#includeTEllipse06.h#includeTEllipse:TEllipse(uintlongR,uintshortR,/uintx,uinty,TColorcolor):TShape(x,y)uint x,uint y,TColor color)_longR=longR;_shortR=shortR;/在派生类构造函数中访问基类保护成员_color=color;TEllipse:TEllipse(uintlongR,uintshortR,/uintx,uinty):TShape(x,y)uint x,uint y)_longR=longR;_shor

33、tR=shortR;例8-6 遗漏的基类构造函数49派生类的构造函数的一般总结派生类的构造函数的一般总结派生类的构造函数的职责1.初始化基类2.初始化对象数据成员3.初始化基本类型的数据成员方式1.构造函数初始化列表2.构造函数函数体除非有特殊要求(const 或者 reference 数据成员只能由初始化列表来获得初值)若不需做上述工作,则可不定义构造函数,而使用系统提供的默认构造函数。50派生类的构造函数派生类的构造函数构造函数的调用次序1.基类的构造函数2.内嵌对象的构造函数3.派生类的构造函数因此基类 和 内嵌对象 的初始化只能放在初始化列表中,不能放到派生类的构造函数体中多继承时,基

34、类构造函数的调用顺序:按照定义派生类时这些基类被继承的顺序按照定义派生类时这些基类被继承的顺序 与他们在初始化列表的次序无关。派生类的多个对象成员的构造函数的调用顺序 按照派生类定义这些成员的顺序进行按照派生类定义这些成员的顺序进行 与他们在初始化列表中的先后次序无关。有多个基类?多个内嵌对象?512024/3/13周三可编辑-52-8.3.4 8.3.4 析构函数析构函数8 8.3.3.4 4 析构函数析构函数 1.派生类不能继承基类的析构函数,需要自己定义析构函数。2.派生类的析构函数一般只负责清理位于堆区的成员,而不需清理位于栈区的成员。3.析构函数的调用次序与构造函数相反1.先派生类析

35、构函数,再基类析构函数 复习:析构函数的功能在对象消亡之前进行必要的清理工作53classTcolorprivate:string_color;public:TColor(stringcolor=BLACK)coutTColor构造函数endl;_color=color;TColor()coutTColor析构函数endl;/Main07.cpp#include#includeusingnamespacestd;classTpointprotected:int_x,_y;public:TPoint(intx=0,inty=0)coutTPoint构造函数(x,y)endl;_x=x;_y=y;

36、TPoint()coutTPoint析构函数(_x,_y)endl;例8-7 派生类析构函数54classTEllipse:publicTShapeprivate:TPoint*pLeftFocus,RightFocus;public:TEllipse():TShape(),RightFocus(2,0)cout派生类构造函数endl;pLeftFocus=newTPoint(1,0);TEllipse()cout派生类析构endl;if(pLeftFocus)deletepLeftFocus;voidmain()TEllipseelps;classTShapeprotected:TColor

37、*pColor;public:TShape()cout基类构造函数endl;pColor=newTColor;TShape()cout基类析构函数endl;if(0!=pColor)deletepColor;例8.7 派生类析构函数552024/3/13周三可编辑-56-8.4 8.4 转换与继承转换与继承8.4 8.4 转换与继承转换与继承深入了解派生类的成员的布局方式派生类对象与基类对象之间转换的一般规则2024/3/13周三可编辑-58-8.4.1 8.4.1 派生类到基类的转换派生类到基类的转换8.4 8.4 转换与继承转换与继承派生类到基类的转换有以下三种情况:派生类对象转换为基类对

38、象;基类对象指针指向派生类对象;用派生类对象初始化基类对象的引用。public:TCircle(intmx=0,intmy=0,intmr=1):TShape(mx,my)r=mr;voidShow()TShape:Show();couttr=r;voidmain()TShapes;TCirclec(1,2,3);coutTShapest;s.Show();coutendl;coutTCirclect;c.Show();coutendl;s=c;/用派生类对象为基类对象赋值/s=static_cast(c);couts=ctt;s.Show();coutendl;/Main08.cpp#inc

39、ludeusingnamespacestd;classTShapeprotected:intx,y;public:TShape(intmx=0,intmy=0)x=mx;y=my;voidShow()coutx=xty=y;classTCircle:publicTShapeprotected:intr;例8-8派生类对象转换为基类对象60voidmain()TCirclec(1,2,3);coutTCirclect;c.Show();coutendl;/TShape*ps=&c;TShape*ps=dynamic_cast(&c);/基类对象指针指向派生类对象if(0!=ps)coutShow

40、();coutendl;/Main09.cpp/本文件的代码除了main()函数之外,均与Main08.cpp相同#includeusingnamespacestd;classTShapeprotected:intx,y;public:TShape(intmx=0,intmy=0)x=mx;y=my;voidShow()coutx=xty=y;classTCircle:publicTShapeprotected:intr;public:TCircle(intmx=0,intmy=0,intmr=1):TShape(mx,my)r=mr;voidShow()TShape:Show();coutt

41、r=r;例8-9基类对象指针指向派生类对象612024/3/13周三可编辑-62-8.4.2 8.4.2 基类到派生类的转换基类到派生类的转换 8.4.2 8.4.2 基类到派生类的转换基类到派生类的转换C+编译器可以自动将派生类对象转换为基类对象(隐式类型转换)从基类到派生类的自动转换是不存在的/以下代码仅为示例TShape s;TCircle c =s;/错误!不能将基类转换为派生类TCircle*pc =&s;/错误!不能将基类转换为派生类TCircle&rc =s;/错误!不能将基类转换为派生类总结总结类的继承性及其相关概念派生类可以以公有、保护和私有3种方式继承基类派生类能够继承基类中除构造函数和析构函数之外的所有成员派生类定义自己的构造函数和析构函数。在定义派生类的构造函数时,不仅要考虑派生类新增数据成员的初始化,还要注意在成员初始化列表中对基类构造函数的调用和内嵌对象数据成员进行初始化。64

展开阅读全文
相似文档                                   自信AI助手自信AI助手
猜你喜欢                                   自信AI导航自信AI导航
搜索标签

当前位置:首页 > 通信科技 > 开发语言

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        获赠5币

©2010-2024 宁波自信网络信息技术有限公司  版权所有

客服电话:4008-655-100  投诉/维权电话:4009-655-100

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :gzh.png    weibo.png    LOFTER.png 

客服