版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C++语言程序设计第十一组C++语言程序设计第八章继承C++语言程序设计1目录C++语言程序设计2“继承的概念基类和派生类派生类的构造和析构多继承基本知识在主函数中增加调试信息编程技能同名覆盖与重载转换与继承刨根问底C++语言程序设计3基本知识a自行车8.1继承的概念自行车BicycleC++语言程序设计4双人自行车TandemBike8.1继承的概念C++语言程序设计58.1继承的概念竞速自行车RacingBikeC++语言程序设计68.1继承的概念山地车MountainBikeC++语言程序设计78.1继承的概念山地车继承了自行车的特征
自行车“派生”出了山地车C++语言程序设计88.1继承的概念类的继承是在现有类的基础之上,创建新类的机制。称现有的类为基类(BaseClass),新建立的类为派生类(DerivedClass)。也可以表述为“父类(ParentClass)—子类(ChildClass)”或者“超类(Superclass)—子类(Subclass)”Bike基类TandemBike派生类派生于intWheel;boolRun();intWheel;boolRun();intSeat;父类子类从基类
继承C++语言程序设计98.1继承的概念“派生”(Derive)可以理解为继承的另外一种说法。“类D继承了类B”可以表述为“类B派生出类D”。若类B派生出类D1、D2…,也可以说B是D1、D2…的泛化(Generalization),称B为D1、D2…的基类,称D1、D2为B的派生类。如果两个类的实现有某些显著的共同点,则将这些共性做成一个基类。面向对象程序设计的难点不在于如何写函数,而在于如何发现类,规划每一个类所需完成的功能,以及准确界定各个类之间的关系。若派生类只有一个直接基类,则称这种继承方式为单继承;若派生类有多个直接基类,则称为多继承。C++语言程序设计10C++语言程序设计118.2定义基类和派生类定义派生类时要声明继承方式,基类的成员被继承到派生类,访问控制受继承方式的影响继承导致一种特殊的语法现象:同名覆盖。三种继承方式public、protected、private不同继承方式的影响主要体现在:派生类成员对基类成员的访问控制派生类对象对基类成员的访问控制8.2定义基类和派生类C++语言程序设计12问题:想在屏幕上画出正三角形、矩形或圆形方法一:结构化方法DrawTri(intx,inty,charcolor,intside);DrawRect(intx,inty,charcolor,intlength,intwidth)DrawCircle(intx,inty,charcolor,intRadius)方法二:面向对象方法classcircle圆形classrectangle矩形classtriangle三角形基类:classshape色彩color位置(x,y)shapecirclerectangletriangle泛化?//TShape01.h:类TShape的头文件typedefunsignedintuint;classTShape{private:uint_x,_y;//几何形状的位置public:TShape();uintgetX();uintgetY();voidsetX(uintx);voidsetY(uinty);voidDraw();};C++语言程序设计138.2定义基类和派生类//TShape01.cpp:类TShape的实现#include"TShape01.h"#include<iostream>usingnamespacestd;TShape::TShape(){_x=10;_y=10;}voidTShape::Draw(){cout<<"ThisisTShape::Draw()"<<endl;}成员函数的分类构造函数设置属性值读取属性值执行//TEllipse01.h:类TEllipse的头文件#include"TShape01.h"classTEllipse:publicTShape{public:voidDraw();};//TEllipse01.cpp:类TEllipse的实现#include"TEllipse01.h"#include<iostream>usingnamespacestd;voidTEllipse::Draw(){cout<<"Drawanellipsewithcolor"<<endl;}成员函数的分类构造函数设置属性值读取属性值执行C++语言程序设计158.2定义基类和派生类//Main01.cpp#include"TEllipse01.h"#include<iostream>usingnamespacestd;intmain(){TEllipsem_TEllipse;cout<<"X="<<m_TEllipse.getX()<<",Y="<<m_TEllipse.getY()<<endl; //显示默认的x、y值m_TEllipse.setX(11u); //修改x的值//m_TEllipse._y=21u; //错误!用户代码不能通过类的
对象访问私有成员m_TEllipse.setY(21u); //修改y的值cout<<"X="<<m_TEllipse.getX()<<",Y="<<m_TEllipse.getY()<<endl; //显示修改后的x、y值m_TEllipse.Draw();return0;}C++语言程序设计168.2定义基类和派生类程序运行结果:
X=10,Y=10
X=11,Y=21
Drawanellipsewithcolor8.2定义基类和派生类派生类定义的语法格式是:class派生类名:
继承方式基类1,继承方式基类2,…,继承方式基类n{派生类成员声明;};例如:已有基类b1和b2,定义派生类derive,其中包括私有整型成员newInt,公有函数成员intnewFun(),私有函数成员intmax(inta,intb);写出类derive的定义。classderive:publicb1,privateb2{private:
intnewInt;public:
voidnewFun();private:
intmax(inta,intb);};C++语言程序设计178.2定义基类和派生类类成员的可见性公共成员:public保护成员:protected私有成员:private继承的方式公有继承(public)保护继承(protected)私有继承(private)派生类继承了基类中的所有成员,但不包括构造函数析构函数默认赋值运算符8.2定义基类和派生类C++语言程序设计18不同继承方式决定的不同访问控制权限体现在:派生类的成员函数对其继承的基类成员的访问控制;其它模块通过派生类对象对其继承的基类成员的访问控制。private:protected:public:基类???派生类publicprotectedprivate继承方式决定继承成员的访问权限继承来的成员的访问权限?8.2定义基类和派生类C++语言程序设计191.公有继承公有继承的派生类定义形式:class派生类名:public基类名{ 派生类新成员定义;};private:protected:public:基类???派生类基类成员
在派生类中的访问属性不变。派生类的成员函数
可以访问基类的公有成员和保护成员,不能访问基类的私有成员;派生类以外的其它函数
可以通过派生类的对象,访问从基类继承的公有成员,但不能访问从基类继承的保护成员和私有成员。privateprotectedpublic派生类成员函数可以访问派生类对象基类成员的属性public8.2定义基类和派生类C++语言程序设计202.私有继承私有继承的派生类定义形式:class派生类名:private基类名{ 派生类新成员定义;};private:protected:public:基类???派生类基类成员
在派生类中的访问属性都变成private。派生类的成员函数
可以访问基类的公有成员和保护成员,不能访问基类的私有成员;派生类以外的其它函数
不能通过派生类的对象,访问从基类继承的任何成员。privateprivateprivate派生类成员函数可以访问基类成员的属性private派生类对象8.2定义基类和派生类C++语言程序设计21private:protected:public:父类privateprotectedprotected子类protectedprivate:protected:public:父类privateprivateprivate:子类privateprivateprivateprivate:孙类privateprotectedpublic孙类成员函数无法访问protectedpublicprivateprotectedprotected孙类孙类成员函数可以访问私有继承和保护继承的区别8.2定义基类和派生类C++语言程序设计22public:protected:private:publicpublicprotectedprivateprotectedprotectedprotectedprivateprivateprivateprivateprivate基类存取方式继承类型派生类继承的基类成员的访问属性继承方式影响访问控制8.2定义基类和派生类C++语言程序设计23同名覆盖(Override):派生类修改基类的成员,是在派生类中声明了一个与基类成员同名的新成员。在派生类作用域内或者在类外通过派生类的对象直接使用这个成员名,只能访问到派生类中声明的同名新成员,这个新成员覆盖了从基类继承的同名成员,这种情况称为同名覆盖。class
base{public:
void
f(){cout<<"base"<<endl;}};class
deriver:public
base{public:
void
f(){cout<<"deriver"<<endl;}};int
main(){
deriver
derobj;
derobj.f();
return0;}输出结果?A:
base
B:deriver在派生类中声明了一个与基类成员同名的新成员OverRide只能访问到派生类中的同名新成员在派生类作用域内或者在类外通过派生类的对象直接使用这个成员名8.3派生类的构造和析构基类的构造函数和析构函数不能被派生类所继承;派生类一般需要定义自己的构造函数和析构函数;派生类的构造及析构函数通常会受到基类构造及析构函数的影响。基类只有无参数构造函数在基类具有无参构造函数,派生类又没有定义构造函数的时候,系统会自动调用基类的无参构造函数来构造派生类对象中的基类成分。基类的构造函数一般被声明为public访问控制方式。若基类提供了一些构造函数,并且只希望由派生类使用这些构造函数,那么就需要在基类中将这样的特殊构造函数定义为protected。C++语言程序设计248.3派生类的构造和析构派生类的构造函数派生类的构造函数要初始化本类的数据成员,还要调用基类的构造函数,并为基类构造函数传递参数,完成派生类中基类成分的初始化。派生类构造函数的形式如下。派生类名::派生类名(基类所需的形参,本类成员所需的形参):
基类1(基类参数表1),基类2(基类参数表2),…,基类n(基类参数表n){
本类基本类型数据成员初始化;}C++语言程序设计25初始化列表//TShape03.cpp#include"TShape03.h"#include<iostream>TShape::TShape(uintx,uinty){_x=x;_y=y;_RED=0;_GREEN=0;_BLUE=0;}TShape::~TShape(){cout<<"TShapedestructed"<<endl;}voidTShape::Draw(){cout<<"ThisisTShape::Draw()"<<endl;}voidTShape::getXY(uint&x,uint&y){x=_x;y=_y;}voidTShape::getRGB(uchar&R,uchar&G,uchar&B){R=_RED;G=_GREEN;B=_BLUE;}//TShape03.htypedefunsignedintuint;typedefunsignedcharuchar;classTShape{private:uint_x,_y;//几何形状的位置protected:/*声明几何形状的颜色。允许TShape的派生类直接访问这些颜色属性,而不允许在类外通过类的对象直接访问这些属性
*/uchar_RED,_GREEN,_BLUE;public:TShape(uintx,uinty);voidgetXY(uint&x,uint&y);voidsetXY(uintx,uinty);voidDraw();voidgetRGB(uchar&R,uchar&G,uchar&B);voidsetRGB(ucharR,ucharG,ucharB);};例8-3单继承派生类构造函数26_longR=longR;_shortR=shortR;//在派生类构造函数中初始化基类保护成员_RED=0x00;_GREEN=0x00;_BLUE=0x00;}TEllipse::~TEllipse(){}voidTEllipse::Draw(){uintx,y;getXY(x,y);//调用基类函数获取椭圆的圆心坐标std::cout<<"Drawanellipsewithcolor(";std::cout<<static_cast<uint>(_RED)<<","<<static_cast<uint>(_GREEN)<<","<<static_cast<uint>(_BLUE)<<")atpoint(";//cout<<_x<<“,”<<_y<<“)”<<endl;//错误!在派生类中不能访
问基类私有成员cout<<x<<","<<y<<")"<<endl;}//TEllipse03.h#include"TShape03.h"classTEllipse:publicTShape{protected:uint_longR,_shortR;public:TEllipse(uintlongR,uintshortR,uintx,uinty);~TEllipse();voidDraw();voidgetR(uint&longR,uint&shortR);voidsetR(uintlongR,uintshortR);};//TEllipse03.cpp#include"TEllipse03.h"#include<iostream>TEllipse::TEllipse(uintlongR,uintshortR,uintx,uinty):TShape(x,y){278.3派生类的构造和析构派生类不能继承基类的析构函数,需要自己定义析构函数,以便在派生类对象消亡之前进行必要的清理工作。派生类的析构函数只负责清理它新定义的成员,一般来说,只清理位于堆区的成员。如果没有特殊指针数据成员需要清理,可以使用由系统提供的默认析构函数。当派生类对象消亡时,系统调用析构函数的顺序与建立派生类对象时调用构造函数的顺序正好相反,即先调用派生类的析构函数,再调用基类的析构函数。C++语言程序设计288.4多继承多继承类结构中,派生类可能有多个直接基类或间接基类。可能会引起成员访问的二义性或不确定性问题。基类数据成员和成员函数继承到两个派生类,然后又继承到第二级派生类,基类的成员有两份拷贝。C++语言程序设计29
classFderiver2:publicbase{private:intm_number;public: Fderiver2(intnumber,intdata):base(data) { m_number=number; cout<<"Fderiver2construction"<<endl; }~Fderiver2(){cout<<"Fderiver2deconstruction"<<endl;}//……};classSderiver:publicFderiver1,publicFderiver2{private:intm_attrib;public: Sderiver(intattrib,intnumber,intvalue,intdata): Fderiver1(value,data),Fderiver2(number,data) { m_attrib=attrib; cout<<"Sderiverconstruction"<<endl; } ~Sderiver(){cout<<"Sderiverdeconstruction"<<endl;}//……};voidmain(){Sderiverobject(3,4,5,6);object.setdata(7);} #include<iostream>usingnamespacestd;classbase{private:intm_data;public:base(intm) { m_data=m; cout<<"baseconstruction"<<endl; }~base(){cout<<"basedeconstruction"<<endl;}voidsetdata(intdata){m_data=data;}intgetdata(intdata){returnm_data;}};classFderiver1:publicbase{private:intm_value;public:Fderiver1(intvalue,intdata):base(data) { m_value=value; cout<<"Fderiver1construction"<<endl; }~Fderiver1(){cout<<"Fderiver1deconstruction"<<endl;}//……};8.4多继承将共同基类设置为虚基类,创建派生类对象时,虚基类的构造函数只会调用一次,虚基类的成员在第三层派生类对象中就只有一份拷贝,不会再引起二义性问题。将共同基类设置为虚基类,需要在第一级派生类时就用关键字virtual修饰说明继承关系,其语法形式:
class派生类名:virtual继承方式基类名{//……}在多继承情况下,虚基类关键字的作用范围和继承方式关键字相同,只对紧随其后的基类起作用。基类的构造函数只调用了一次,也就不会出现基类成员的重复拷贝。C++语言程序设计31C++语言程序设计编程技能b32(一)在主函数中增加调试信息有3种办法观察程序的运行,对应3种程序除错技术(“debug”)。①
通过阅读程序的办法分析程序的流程,也称为“静态代码复查”。②
在构造函数中增加一些输出语句,当程序执行这些语句时,相关信息就可以显示在输出设备上。③
使用开发工具提供的调试器,在程序中设置断点,执行程序时单步跟踪代码的运行结果。这是最强大、最常用的程序除错方法,也是每一个程序员必须掌握的基本功。②③方法必须执行程序才能获得信息,称为“动态除错”。C++语言程序设计为了验证TShape的构造函数被调用,可以在TShape::TShape(uintx,uinty)函数体中增加一条语句cout<<“ThisisTShape(uint,uint)”<<endl称为“cout大法”。cout<<__FILE__<<“:”<<__LINE__<<““;其中“__FILE__”和“__LINE__”是C++编译器提供的宏,分别对应“当前文件名”和“当前行号”。33刨根问底cC++语言程序设计34(I)同名覆盖与重载C++语言程序设计35Override与Overload:前者是“同名覆盖”,在类继承中才会出现;后者是“重载”,在同一作用域范围内,由参数个数或类型不同的多个同名函数构成,可以单独出现,也可以与Override现象同时出现。一般来说,同名覆盖现象中的多个函数原型(函数类型、名字、参数)是相同的,而重载现象中的多个函数原型(参数)是不同的。11.voidfunc(){cout<<"deriver::func()"<<endl;}12.voidfunc(intx){cout<<"deriver::func("<<x<<")"<<endl;}13.};14.intmain(){15.basem_base;16.deriverm_deriver;17.m_base.func();18.m_deriver.func();19.m_deriver.func(10);20.return0;21.}1.//例8-7,包含1个文件:Main07.cpp2.//Main07.cpp3.#include<iostream>4.usingnamespacestd;5.classbase{6.public:7.voidfunc(){cout<<"base::func()"<<endl;}8.};9.classderiver:publicbase{10.public:第11行与第12行代码函数名相同而参数不同,形成了重载;第7行与第11行的函数原型相同但是分别处于基类与派生类中,构成了同名覆盖。(II)转换与继承C++语言程序设计36每个派生类对象包含一个基类部分,这意味着可以像使用基类对象一样在派生类对象上执行基类的操作,这就涉及派生类基类的转换。该转换包括以下3种情况。派生类对象转换为基类对象。用派生类对象给基类对象赋值基类对象指针指向派生类对象。用派生类对象初始化基类对象的引用。public:TCircle(intmx=0,intmy=0,intmr=1):TShape(mx,my){r=mr;}voidShow(){TShape::Show();cout<<"\tr="<<r;}};intmain(){TShapes;TCirclec(1,2,3);
cout<<"TShapes\t";s.Show();cout<<endl;cout<<"TCirclec\t";c.Show();c
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年中职(建筑防水工程技术)防水卷材施工阶段测试试题及答案
- 2025年大学心理健康(人际交往)试题及答案
- 2025年中职图书馆学(图书馆学基础)试题及答案
- 2025年中职中西面点(酥点制作工艺)试题及答案
- 2025年高职物业管理(物业绿化养护)试题及答案
- 2025年高职电子信息材料应用技术(材料性能检测)试题及答案
- 2025年大学大四(农林经济管理)农林经济管理综合实训阶段测试题及答案
- 2025年中职农业机械使用与维护(农机操作规范)试题及答案
- 2025年高职宠物医疗技术(犬猫外科护理)试题及答案
- 2025年高职化学(有机化学)试题及答案
- 电动两轮车整车性能测试与优化方案
- 《艺术插花的造型与数学》教学大纲
- SF-36健康调查量表(含excel版)
- 超星尔雅学习通《高校实验室安全基础课(实验室准入教育)》章节测试含答案
- 酒店餐饮宴会服务流程规定
- 2024-2025学年山东省潍坊市高一下学期5月期中考试政治试题(解析版)
- 环境污染治理设施运营考试试题
- 2025年证监会招聘面试高频考题及解析
- 2025-2030中国溶剂染料行业消费状况及竞争策略分析报告
- 急诊科脑出血课件
- 安全生产管理机构人员配备表
评论
0/150
提交评论