欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    第1章C++基础1.ppt

    • 资源ID:87474518       资源大小:603.50KB        全文页数:57页
    • 资源格式: PPT        下载积分:16金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要16金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    第1章C++基础1.ppt

    第一章第一章C+基础基础1.1C+概述概述1.2类和对象类和对象1.3继承和派生继承和派生1.4多态和虚函数多态和虚函数 1.1.1 C+程序创建 使用C+高级语言编写的程序称为源程序源程序。由于计算机执行由0和1组成的二进制指令(称为机器代码)机器代码),因而C+源程序是不能被计算机直接执行的,必须转换成机器代码才能被计算机执行。这个转换过程就是编译器对源代码进行编译编译和连连接接的过程。如图1.1所示。源代码编译器目标代码连接程序可执行代码库其他代码图图1.1 C+程序创建过程程序创建过程1.1C+概述概述1.1C+概述概述 Visual C+是Microsoft公司推出的目前使用极为广泛的基于Windows平台的可视化编程环境。Visual C+6.0是在以往版本不断更新的基础上形成的,由于其功能强大、灵活性好、完全可扩展以及具有强有力的Internet支持,在各种以C/C+语言为内核的Windows开发工具中脱颖而出,成为目前流行的Windows应用程序开发的集成开发环境,如图1.2所示。图图1.2 Visual C+6.05 SP6开发环境开发环境1.1C+概述概述 1.创建工作文件夹创建工作文件夹创建Visual C+6.0的工作文件夹“D:Visual C+应用”,以后所有创建的C+程序都在此文件夹下,这样既便于管理,又容易查找。在文件夹“D:Visual C+应用”下再创建一个子文件夹“第1章”用于存放第1章中的C+程序;对于第2章程序就存放在子文件夹“第2章”中,依此类推。2.启动启动Visual C+6.0图图1.3 “每日提示每日提示”对话框对话框选择“开始”“程序”“Microsoft Visual Studio 6.0”“Microsoft Visual C+6.0”,运行Visual C+6.0。第一次运行时,将显示如图1.3的“每日提示”对话框。单击下一条按钮,可看到有关各种操作的提示。如果在启动时显示提示复选框中单击鼠标,去除复选框的选中标记“”,那么下一次运行Visual C+6.0,将不再出现此对话框。单击关闭按钮关闭此对话框,进入Visual C+6.0开发环境。图图1.3 “每日提示每日提示”对话框对话框1.1C+概述概述 3.添加添加C+程序程序 (1)单击标准工具栏 上的“新建”()按钮,打开一个新的文档窗口,在这个窗口中输入下列C+代码。例例Ex_Simple 一个简单的一个简单的C+程序程序/*第一个简单的C+程序*/#include int main()double r,area;/定义变量coutr;/从键盘上输入变量r的值area=3.14159*r*r;/计算面积cout圆的面积为:arean;/输出面积return 0;/指定返回值 1.1C+概述概述 (2)选择“文件”“保存”菜单或按快捷键Ctrl+S或单击标准工具栏的“”按钮,弹出“保存为”文件对话框。将文件定位到“D:Visual C+应用第1章”文件夹中,文件名指定为“Ex_Simple.cpp”(注意扩展名.cpp不能省略,cpp是C Plus Plus的缩写,即“C+”的意思)。4.编译和运行编译和运行 (1)单击编译工具条 上的生成工具按钮“”或直接按快捷键F7,系统弹出一个对话框,询问是否为该程序创建默认的活动工作区间文件夹,单击是按钮,系统开始对Ex_Simple进行编译、连接,同时在输出窗口中显示编连的有关信息,当出现:表示Ex_Simple.exe可执行文件已经正确无误地生成了。(2)单击编译工具条 上的运行工具按钮“”或直接按快捷键Ctrl+F5,就可以运行刚刚生成的Ex_Simple.exe了,结果弹出这样的控制台窗口(其属性已被修改过):1.1C+概述概述此时等待用户输入一个数。当输入10并按Enter键后,控制台窗口显示为:其中,“Press any key to continue”是Visual C+自动加上去的,表示Ex_Simple运行后,按一个任意键将返回到Visual C+开发环境,这就是C+程序的创建、编连和运行过程。上述生成的程序又可叫“控制台应用程序”,它是指那些需要与传统DOS操作系统保持程序的某种兼容,同时又不需要为用户提供完善界面的程序。简单地讲,就是指在Windows环境下运行的DOS程序。控制台窗口就是一个DOS屏幕!1.1C+概述概述1.1.2 C+程序结构 每一个C+程序源文件通常是以.cpp(c plus plus,C+)为扩展名,它是由编译预处理指令、数据或数据结构定义以及若干个函数组成。下面就以Ex_Simple.cpp的程序代码(如图1.4所示)来分析C+程序的组成和结构:1.main函数函数代码中,main表示主函数主函数,由于每一个程序执行时都必须从main开始,而不管该函数在整个程序中的具体位置,因此每一个C+程序或由多个源文件组成的C+项目都必须包含一个且只有一个main函数。图图1.4 Ex_Simple.cpp的程序代码的程序代码1.1C+概述概述 2.头文件包含头文件包含 行号为行号为3的代码是C+文件包含#include的编译指令,称为预处理指令预处理指令。#include后面的iostream.h是C+编译器自带的文件,称为C+库文件库文件,它定义了标准输入/输出流的相关数据及其操作,由于程序用到了输入/输出流对象cin和cout,因而需要用#include将其合并到程序中,又由于它们总是被放置在源程序文件的起始处,所以这些文件被称为头文件头文件(Header File)。C+编译器自带了许多这样的头文件,每个头文件都支持一组特定的“工具”,用于实现基本输入输出、数值计算、字符串处理等方面的操作。3.注释注释 通常,必要的注释内容应包含:在源文件头部进行必要的源程序的总体注释总体注释:版权说明、版本号、生成日期、作者、内容、功能、与其它文件的关系、修改日志等,头文件的注释中还应有函数功能简要说明。在函数的头部进行必要的函数注释函数注释:函数的目的/功能、输入参数、输出参数、返回值、调用关系(函数、表)等。其他的少量注释其他的少量注释。如全局变量的功能、取值范围等。千万不要陈述那些一目了然的内容,否则会使注释的效果适得其反。需要说明的是,C+中的“/*.*/”是用来实现多行的注释,它是将由“/*”开头到“*/”结尾之间所有内容均视为注释,称为块注释块注释。块注释(“/*.*/”)的注解方式可以出现在程序中的任何位置,包括在语句或表达式之间。而“/”只能实现单行的注释,它是将“/”开始一直到行尾的内容作为注释,称为行注释行注释。1.1C+概述概述1.1.3 C+程序组成下面再看2个C+程序:例例Ex_Simple1 在屏幕上输出一个由星号形成的三角形在屏幕上输出一个由星号形成的三角形 /输出星号的三角形阵列#include void DoDraw(int num);/声明一个全局函数 int main()int num=5;/定义并初始化变量 DoDraw(num);/函数的调用 return 0;/指定返回值 void DoDraw(int num)/函数的定义 for(int i=0;i num;i+)/循环语句 for(int j=0;j=i;j+)cout*;cout n;1.1C+概述概述 本程序包括两个函数:主函数main和被调用的函数DoDraw。DoDraw函数是在屏幕上输出星号的三角形阵列,这个阵列的行数以及每行星号的个数由num决定。程序运行的结果如下:在以后的C+程序运行结果中,本书不再完整显示其控制台窗口,也不再显示“Press any key to continue”,仅将控制台窗口中运行结果部分裁剪下来列出,并加以单线阴影边框,本书作此约定本书作此约定。1.1C+概述概述 例例Ex_Simple2 用类的概念重写例用类的概念重写例Ex_Draw#include class CDrawArray /定义一个类public:void DoDraw(int num);/声明类的公有成员函数;void CDrawArray:DoDraw(int num)/成员函数的实现for(int i=0;inum;i+)for(int j=0;j=i;j+)cout*;coutn;int main()int num=5;CDrawArray myDraw;/定义类的一个对象myDraw.DoDraw(num);/调用此对象的成员函数return 0;/指定返回值1.2类和对象类和对象 面向对象的程序设计有三个主要特征:封装封装、继承继承和多态多态。(1)封装封装。封装是将数据和代码捆绑到一起,避免了外界的干扰和不确定性。在在C+中,中,封装是通过类来实现的封装是通过类来实现的。类是用来描述具有相同的属性和方法的对象的集合,它定义了该集合中每个对象所共有的属性和方法。(2)继承继承。继承是让某个类型的对象获得另一个类型的对象的特性。在C+面向对象程序设计中,继承是指一个子类继承父类(或称为基类)的特征。通过继承可以实现代码的重重用用:从已存在的类派生出的一个新类将自动具有原来那个类的特性,同时,它还可以拥有自己的新特性。(3)多态多态。对于相同的消息,不同的对象具有不同的反应的能力。多态机制使具有不同内部结构的对象可以共享相同的外部接口,通过这种方式减少代码的复杂度。总之,面向对象的程序设计是将问题抽象成许多类,将数据与对数据的操作封装在一起,各个类之间可以存在着继承关系,对象是类的实例,程序是由对象组成。因此,在C+面向对象程序设计,首先设计类,定义类的属性和可执行的操作(方法),然后设计使用这些类的对象的程序。这种从低级(如类)到高级(如程序)的处理过程称为自下向上自下向上的编程方式。1.2类和对象类和对象1.2.2 类的声明 C+中,声明一个类的一般格式如下:class /声明部分private:public:protected:;/实现部分类类体体1.2类和对象类和对象 成员函数成员函数是用来对数据成员进行操作,又称为方法方法。注意,类体中最后一个花括号后最后一个花括号后面的分号面的分号“;”不能省略不能省略。在Visual C+中,常用大写的C字母开始的标识符作为类名,C用来表示类(Class),以与对象、函数及其他数据类型的名称相区别。当类的成员函数的定义是在类体外部完成时,必须用作用域运算符作用域运算符“:”来告知编译系统该函数所属的类类。此时,成员函数的定义格式如下::()函函数数体体1.2类和对象类和对象 例例Ex_StuScoreClass 一个类的定义一个类的定义示例示例 需要说明的是:(1)类中的数据成员的数据类型可以是任意的,包含整型、浮点型、字符型、数组、指针和引用等,也可以是另一个类的对象。例如:class COne ;class CTwo private:COne a;/数据成员a是已定义的COne类对象 ;1.2类和对象类和对象 (2)由于类是一种数据类型,系统并不会为其分配内存空间,所以在定义类中的数据成员时,不能对其进行初始化,也不能指定除static之外的任何存储类型。例如类CStuscore中,下面的定义是错误的:class CStuscore private:floatfScore3=80.0,90.0,78.0;/错误:不能在直接对数据成员进行初始化错误:不能在直接对数据成员进行初始化 auto int n;/错误:不合法的存储类型错误:不合法的存储类型 ;(3)访问权限关键词public、private、protected在类中使用先后次序无关紧要,且可使用多次。每个访问权限关键词为类成员所确定的访问权限是从该关键词开始到下一个关键词为止。如在CStuscore类中,私有数据成员是用两个private来分开写成二个部分。同样,若将公有成员函数用两个public分开写成二个部分,仍是正确的。1.2类和对象类和对象 (4)在进行类设计时,通常将数据成员的声明为私有的,而将大多数成员函数声明成公有的。这样,类以外的代码不能直接访问类的访问权限私有数据,从而实现了数据的封装数据的封装。而公有成员函数可为内部的私有数据成员提供外部接口,但接口实现的细节在类外又是不可见的,这就是C+类的优点之一。(5)一般来说,程序员更多关心的是public成员,因此常将public成员写在类体中的前面,而将private成员写在类体中的后面。若在类体内没有指定成员的访问权限,则默认的访问权限为私有的私有的(private)。(6)当程序比较大时,应尽量将类单独存放在一个文件中或将类的声明放在头文件中而将成员函数的实现放在与头文件同名的.cpp文件中(这也是Visual C+6.0的编程方式)。1.2类和对象类和对象 1.2.3 对象的定义和初始化 类对象有3种定义方式:声明之后定义声明之后定义、声明之时定义声明之时定义和一次性定义一次性定义。例如:class A ;A a;/声明之后定义 class B b,c;/声明之时定义 class d,e;/一次性定义 但由于“类”比任何数据类型都要复杂得多,为了提高程序的可读性,真正将“类”当成一个密闭、“封装”的盒子(接口),在程序中应尽量使用对象的声明之后定义声明之后定义方式,即按下列格式进行:;1.2类和对象类和对象 其中,类名类名是已声明过的类的标识符,对象名可以有一个或多个,多个时要用逗号逗号隔开。被定义的对象既可以是一个普通对象,也可以是一个数组对象或指针对象。例如:CStuscore one,*Stu,Stus2;这时,one是类CStuscore的一个普通对象,Stu和Stus分别是该类的一个指针对象和对象数组。若对象是一个指针,则还可像指针变量那样进行初始化,例如:CStuscore *two=&one;可见,在程序中,对象的使用和变量是一样的,只是对象还有成员的访问等手段。1.2.4 对象成员的访问 一个对象的成员就是该对象的类类所定义的数据成员和成员函数。访问对象的成变量和成员函数与访问一般变量和函数的方法是一样的,只不过须在成员前面加上对象名和成员运算符“.”,其表示方式如下:.()1.2类和对象类和对象 例如:coutone.getName()endl;/调用对象one中的成员函数getName,然后输出其结果 cout Stus0.getNo()endl;/调用对象数组元素Stus0中的成员函数getNo,然后输出 需要说明的是,一个类对象只能访问该类的公有型成员类对象只能访问该类的公有型成员,而对于私有型成员则不能访问,例如getName和getNo等公有成员可以由对象通过上述方式来访问,但strName、strStuNo、fScore等私有成员不能被对象来访问。若对象是一个指针,则对象的成员访问形式如下:-()1.2类和对象类和对象 “-”是另一个表示成员的运算符,它与“.”运算符的区别是:“-”用来表示指向对象的指针的成员,而“.”用来表示一般对象的成员。需要说明的是,下面的两种表示是等价的(对于成员函数也适用):-(*).例如:CStuscore *two=&one;cout(*two).getName()endl;/A coutgetName()endl;/与A等价 需要说明的是,类外通常是指在子类(后面会讨论)中或其对象等的一些场合,对于访问权限public、private和protected来说,只有在子类中或用对象来访问成员时,它们才会起作用。在用类外对象来访问成员时,只能访问public成员,而对private和protected均不能访问。对类中的成员访问或通过该类对象来访问成员都不受访问权限的限制。1.2类和对象类和对象 1.2.5 构造函数和析构函数(1)构造函数)构造函数 前面已提及,在类的定义中是不能不能对数据成员进行初始化的。为了能给数据成员设置某些初值,这时就要使用类的特殊成员函数构造函数构造函数。构造函数的最大特点是在对象建立时它会被自动执行自动执行,因此用于变量、对象的初始化代码一般放在构造函数中。C+规定,一个类的构造函数必须与相应的类同名,它可以带参数,也可以不带参一个类的构造函数必须与相应的类同名,它可以带参数,也可以不带参数,与一般的成员函数定义相同,可以重载,也可以有默认的形参值数,与一般的成员函数定义相同,可以重载,也可以有默认的形参值。例如:程序运行的结果为:分析和说明:(1)代码中,为类CPerson定义了3个重载的构造函数(程序中用A、B、C标明)。这些构造函数的重载重载必须按其规定进行定义:要么参数个数不同;要么参数个数相同,但参数类型不能相同。其中,构造函数CPerson(float h,float w=120),不仅设置了形参w的默认值,而且还将该构造函数的声明在类中进行,其定义在类体外实现。1.2类和对象类和对象 (2)主函数main中,对象one的初始化等价于one.CPerson(DING),因而调用的是B构造函数,此时对象的私有数据成员name设定了初值“DING”,而height和weight初值没有指定,它们的初值取决于对象的存储类型,可能是默认值或无效值。(3)对象two的初始化等价于two.CPerson(170,130),因而调用的是C构造函数,此时对象的私有数据成员height和weight初值分别设定为170、130,而name初值没有指定,它可能是默认值或无效值。(4)对象three的初始化等价于three.CPerson(DING,170,130),因而调用的是A构造函数,此时对象的私有数据成员name、height和weight初值分别设定为DING、170和130。在C+函数声明时,自右向左可以为一个或多个形参指定默认的参数值,这样在调用时,可以不给出具体的实际参数值,而按其指定的默认值工作。如CPerson(float h,float w=120)构造函数,在定义对象时,若有CPerson other(170)。则使得height=170,而weight等于默认值120。1.2类和对象类和对象 虽然构造函数的定义方式与一般成员函数没有什么区别,但要注意:构造函数名必须与类同名构造函数名必须与类同名。只有约定了构造函数名,系统在生成类的对象时,才能自动调用类的构造函数。定义的构造函数不能指定其返回值的类型,也不能指定为定义的构造函数不能指定其返回值的类型,也不能指定为void 类型类型。事实上,由于构造函数主要用于对象数据成员的初始化,因而无须返回函数值,也就无须有返回类型。若要用类定义对象,则构造函数必须是公有型公有型成员函数,否则类无法实例化。若类仅用于派生其它类,则构造函数可定义为保护型保护型成员函数。当构造函数重载以及设定构造函数默认形参值时,要避免出现二义性二义性。例如:CPerson(char*str,float h=170,float w=130)/A strcpy(name,str);height=h;weight=w;CPerson(char*str)/B strcpy(name,str);1.2类和对象类和对象 则当“CPerson other(“DING”);”时,即“other.CPerson(“DING”);”,因编译无法确定是上述哪一个构造函数的调用,从而出现编译错误出现编译错误。如果没有定义任何构造函数,则编译自动为类隐式隐式生成一个不带任何参数不带任何参数的默认构造函数,由于函数体是空块,因此默认构造函数不进行任何操作,仅仅为了对象创建时的语法需要。例如,对于CPerson类来说,默认构造函数的形式如下:CPerson()/默认构造函数的形式 默认构造函数的目的是使下列对象定义形式合法:CPerson one;/即:one.CPerson();会自动调用默认构造函数 此时,由于对象one没指定任何初值,因而编译会自动调用类中隐式生成的默认构造函数对其初始化。当类定义中指定了构造函数,则隐式的默认构造函数不再存在,因此,若对于前面定义的CPerson类来说,若有:CPerson four;/错误错误1.2类和对象类和对象2.析构函数析构函数与构造函数相对应的是析构函数析构函数(Destructor)。析构函数是C+类中另一个特殊的成员函数,它只是在类名称前加上一个“”符号(逻辑非),以与构造函数功能相反。其格式如下:()这样,数据成员(尤其是用new为其开辟的内存空间)的释放代码就可放入析构函数的函数体中,以便对象消失后自动调用。需要说明的是:(1)每一个类最多只能有一个析构函数,且应为public,否则类实例化后无法自动调用析构函数进行释放,但不能被重载,没有任何参数,也不返回任何值,函数名前也不能有 任何关键词(包括void)。例如:class CPerson public:.CPerson()/析构函数.;1.2类和对象类和对象 (2)与类的其他成员函数一样,析构函数的定义也可在类体外进行,但必须指明它所属的类,且在类体中还必须有析构函数的声明。例如:class CPerson public:.CPerson();/析构函数的声明.;CPerson:CPerson()/在类体外进行析构函数的定义 (3)与默认构造函数类似,若类的声明中没有定义析构函数时,则编译也会自动生成一个隐式的不做任何操作的默认析构函数。1.2.6 new和delete 由于一个类的成员的数据类型可以是任何有效的合法的类型,因而若数据类型为指针时,则这样的成员称为指针成员指针成员,但此时要注意指针成员的潜在危险指针成员的潜在危险。例如,若有一个类CName,用来描述一个字符串名称:1.2类和对象类和对象 由于“CName one(p);”调用的是B重载构造函数,从而使得私有指针成员strName指向等于p的指向。而p是指向new开辟的内存空间,其内容为“DING”,一旦p指向的内存空间删除后,p的指向就变得不确定了,此时strName指向也不确定,所以此时运行结果为:显然,输出的是一个无效的字符串无效的字符串。因此,为了保证类的封装性,类中的指针成员所为了保证类的封装性,类中的指针成员所指向的内存空间必须在类中自行独立开辟和释放指向的内存空间必须在类中自行独立开辟和释放。因此,类CName应改成下列代码:这样,主函数中的代码才会正确的运行结果:1.2类和对象类和对象 1.2.7 对象赋值和拷贝构造函数 1.对象赋值对象赋值 在C+中,一个类的对象的初值设定可以有多种形式。例如,对于前面的类CName来说,则可有下列对象的定义方式:CName o1;/通过A显式默认构造函数设定初值 CName o2(“DING”);/通过B重载构造函数设定初值 等都是合法有效的。但是若有:o1=o2;/通过赋值语句设定初值 则虽合法,因为同类型的变量可以直接用“=”赋值,但运行后却会出现程序终止,这是为什么呢?这是因为对于“CName o1;”这种定义方式,编译会自动调用相应的默认构造函数,此时显式的默认构造函数使私有指针成员strName为空值;而“o1=o2;”中,C+赋值运算符的操作是将右操作对象的内容拷贝(复制)到左操作对象的内存空间中,由于左操作对象o1中的strName没有指向任何内存空间,因此试图将数据拷贝到一个不存在的内存空间中,程序必然异常终止。所以“o1=o2;”看上去合法,但实际上是不可行不可行的。C+还常用下列形式的初始化来将另一个对象作为对象的初值:1.2类和对象类和对象()例如:CName o2(“DING”);/A:通过构造函数设定初值 CName o3(o2);/B:通过指定对象设定初值 B语句是将o2作为o3的初值,同o2一样,o3这种初始化形式要调用相应的构造函数,但此时找不到相匹配的构造函数,因为CName类没有任何构造函数的形参是CName类对象。事实上,CName还隐含一个特殊的默认构造函数,其原型为 CName(const CName&),这种特殊的默认构造函数称为默认拷贝构造函数。默认拷贝构造函数。在C+中,每一个类总有一个默认拷贝构造函数默认拷贝构造函数,其目的是保证B语句中对象初始化形式的合法性,其功能就等价于“CName o3=o2;”。但语句“CName o3(o2);”与语句“o1=o2;”一样,也会出现程序终止,其原因和“o1=o2;”原因一样。但是,若有类CData:1.2类和对象类和对象 class CData public:CData(int data=0)m_nData=data;CData()int getData()return m_nData;private:int m_nData;则下列初始化形式却都是合法有效的:CData a(3);/通过重载构造函数设定初值 CData b(a);/通过默认拷贝构造函数默认拷贝构造函数设定初值,/等价于 CData b=a;cout a.getData()endl;/输出 3 cout b.getData()endl;/输出 31.2类和对象类和对象可见,同变量一样,在C+中类对象的初始化也可以有2种方式:赋值方式和默认拷贝方式。这两种方式是等价的,例如:CData b(a);和CData b=a;是等价的。2.分析和比较分析和比较 解决CName对象初始化所进行的内容拷贝问题,在C+中有2种手段,一是给“=”运算符赋予新的操作,称为运算符重载运算符重载;二是重新定义或重载默认拷贝构造函数。3.浅拷贝浅拷贝 前面已说过,每一个C+类都有一个隐式的默认拷贝构造函数,其目的是保证对象拷贝初始化方式的合法性,其功能是将一个已定义的对象所在的内存空间的内容依次拷贝到被初始化的对象的内存空间中。这种仅仅将内存空间的内容拷贝的方式称为浅拷贝浅拷贝。也就是说,默认拷贝构造函数是浅拷贝浅拷贝方式。4.深拷贝深拷贝 事实上,对于数据成员有指针类型的类来说,均会出现如CName类的问题,由于默认拷贝构造函数无法解决,因此必须自己定义一个拷贝构造函数,在进行数值拷贝之前,为指针类型的数据成员另辟一个独立的内存空间。由于这种拷贝还需另辟内存空间,因而称其为深拷贝深拷贝。1.2类和对象类和对象5.拷贝构造函数拷贝构造函数 拷贝构造函数是一种比较特殊的构造函数,除遵循构造函数的声明和实现规则外,还应按下列格式进行定义。(参数表参数表)可见,拷贝构造函数的格式就是带参数的构造函数。由于拷贝操作实质是类对象空间的引用,因此C+规定,拷贝构造函数的参数个数可以1个或多个,但左起的第1个参数必须是类的引用对象,它可以是“类名&对象”或是“const类名&对象”形式,其中“类名”是拷贝构造函数所在类的类名。也就是说,对于CName的拷贝构造函数,可有下列合法的函数原型:CName(CName&x);/x为合法的对象标识符 CName(const CName&x);CName(CName&x,);/“”表示还有其他参数 CName(const CName&x,);1.2类和对象类和对象 需要说明的是,一旦在类中定义了拷贝构造函数,则隐式的默认拷贝构造函数和隐式的默认构造函数就不再有效了。例如,下面的示例是在前面CName的基础上添加拷贝构造函数的定义,程序如下:例例Ex_CopyCon 使用拷贝构造函数使用拷贝构造函数 代码中,类CName定义了两个拷贝构造函数A和B,其中A称为显式的默认拷贝构造显式的默认拷贝构造函数函数,B称为重载拷贝构造函数重载拷贝构造函数,它还带有字符指针参数,用来将新对象的数据成员字符指针strName指向一个开辟的动态内存空间,然后将另一个对象one的内容复制到 strName中,最后调用cstring头文件定义的库函数strcat将字符指针参数add指向的字符串连接到strName中。程序运行的结果如下:1.2类和对象类和对象 1.2.8 this指针 例例Ex_This 使用使用this指针指针 类CPoint中,使用this指针的成员函数是Copy,此时this指针指向类自己,在成员函数Copy中,由于语句“*this=one”等到对象调用时才会执行,因而当在main函数调用“pt1.Copy(pt2);”时,this指针指向对象pt1,此时“*this=one”是将one的内容拷贝到类对象pt1中,这样就使得pt1的数据成员的值等于pt2的数据成员的值。因此main函数中最后的语句“pt1.print();”输出的结果就是等于pt2的结果。程序运行的结果如下:1.2类和对象类和对象 事实上,当成员函数的形参名与该类的成员变量名同名时,则必须用this指针来显式区分,例如:class CPoint public:CPoint(int x=0,int y=0)this-x=x;this-y=y;void Offset(int x,int y)(*this).x+=x;(*this).y+=y;void Print()const coutPoint(x,y)endl;privateint x,y;代码中,类CPoint中的私有数据成员x、y和构造函数、Offset成员函数的形参同名,正是因为成员函数体中使用了this指针,从而使函数中的赋值语句合法有效,且含义明确。否则,如果没有this指针,则构造函数中的赋值语句就变为了“x=x;y=y;”,显然是不合法的。1.3继承和派生继承和派生 1.3.1 继承的特性 在C+中,类的继承具有下列特性:(1)单向性单向性。类的继承是有方向的类的继承是有方向的。例如,若A类是子类B的父类,则只有子类B继承了父类A中的属性和方法,在B类中可以访问A类的属性和方法,但在父类A中却不访问子类B的任何属性和方法。而且,类的继承还是单向的类的继承还是单向的。例如,若A类继承了B类,反之,此时B类不能再继承A类。同样,若A类是B类的基类,B类是C类的基类,此时C类不能是A类的基类。(2)传递性传递性。若A类是B类的基类,B类是C类的基类,则基类A中的属性和方法传递给了子类B以后,通过子类B也传递给子类C,这是类继承的传递性传递性。正是因为继承的传递性,才使子类自动自动获得基类的属性和方法。(3)可重用性可重用性。自然界中存活在同物种具有遗传关系的层次层次通常是有限的,而C+中的类却不一样,类的代码可一直保留。这样,当基类的代码构造完之后,其下一代的派生类的代码往往新增一些属性和方法,这些一代一代派生下去,整个类的代码越来越完善。若将若干代的类代码保存在一个头文件中,而在新的程序文件中包含进来,然后定义一个派生类,则这样的派生类就具有前面所有代基类的属性和方法,而不必从头开始重新定义和设计,从而节略了大量的代码。可见,类的继承机制也体现了代码重用代码重用或软件重用软件重用的思想。1.3继承和派生继承和派生1.3.2 派生类的定义 在C+中,一个派生类的定义可按下列格式:class :,;基类列表基类列表 从格式可以看出:(1)一个派生类和一个一般类的定义格式基本相同,惟一区别就在于:派生类定义时派生类名后面是由冒号“:”引导的基类列表基类列表。(2)基类列表中,若指定基类只有一个,则这样的派生类是单继承单继承方式,若有多个基类,则为多继承多继承方式。当有多个基类时,基类名之间要用逗号分隔。(3)各基类名之前一般需要指定其继承方式继承方式,用来限定派生类继承基类属性和方法的使用权限。C+继承方式有3种:public(公有)、private(私有)及protected(保护),若继承方式没有指定,则被默认指定为默认指定为private(私有)方式(私有)方式。1.3继承和派生继承和派生 基类必须是在派生类定义前已作过定义的类,若是在派生类后面定义,而仅仅在派生类定义前作基类的提前声明,则是不合法不合法的。例如,下面的代码:class CBase;/基类CBase作提前声明 class CDerived:public CBase/错误错误:CBase未定义未定义 int z;class CBase/基类的定义 int x,y;1.3.3 继承方式 (1)公有继承)公有继承。公有继承(public)方式具有这样特点:在派生类中,基类的公有成员、保护成员和私有成员的访问属性保持不变。在派生类中,只有基类的私有成员是无法访问的。也就是说,基类的私有成员在派生类中被隐藏了,但不等于说基类的私有成员不能由派生类继承。派生类对象只能访问派生类和基类的公有(public)成员。1.3继承和派生继承和派生 2.私有继承私有继承。私有继承(private)方式具有这样特点:在派生类中,基类的公有成员、保护成员和私有成员的访问属性都将变成私有(private),且基类的私有成员在派生类中被隐藏。因此,私有继承方式下,在派生类中仍可访问基类的公有(public)和保护(protected)成员。由于基类的所有成员在派生类中都变成私有,因此基类的所有成员在派生类的子类中都是不可见的。换句话说,基类的成员在派生类的子类中已无法发挥基类的作用,实际上相当于终止基类的继续派生。正因为如此,实际应用中私有继承的使用情况一般比较少见。另外,派生类对象只能访问派生类的共有成员,而不能访问基类的任何成员。3.保护继承保护继承。保护继承(protected)方式具有这样特点:在派生类中,基类的公有成员、保护成员的访问属性都将变成保护的,同样,基类的私有成员在派生类中也是被隐藏的。同私有继承一样,在保护继承方式下,派生类中仍可访问基类的公有成员和保护成员。但派生类对象只能访问派生类的共有成员,而不能访问基类的任何成员。下面来看一个示例,它是反映类CPerson和类CStudent的公有(public)继承关系。在学生类CStudent中,它的数据成员可以有:姓名、学号、性别、年龄、三门课程的成绩、总分和平均分。以往设计这个类时,是将这些数据成员一并声明在CStudent类中,这样做的缺点是显然的,因为若还需要一个教职员工类CStaff,而该类的数据成员也需要姓名、性别和年龄,则还需要重新定义这些数据,显然类代码起不到优化和重用的作用。如果将其中的姓名、性别和年龄的数据成员作为基类CPerson的数据成员,处理这些数据的方法也在基类完成。这样通过继承,使得CStudent和CStaff类同时拥有基类的数据成员及其方法,从而大大简化了类CStaff和CStudent的代码,这在复杂的类设计中尤为重要。1.3继承和派生继承和派生 例例Ex_PublicDerived 派生类的公有继承派生类的公有继承示例示例 分析和说明:(1)基类CPerson包含:私有数据成员name(姓名)、sex(性别)和age(年龄),公有构造函数CPerson、成员函数SetNameAndSex(用于重新设置name和sex),保护成员函数SetAge(用来重新设置age)、ShowInfo(用来显示这些信息)。这样,用基类CPerson创建对象后,对象只能调用共有成员函数SetNameAndSex,而对于私有和保护成员是无法访问的。(2)派生类CStudent的成员除了自身的成员外,实际上还包含了基类CPerson的所有成员。由于CStudent类公有继承了CPerson类,因此可以在派生类中访问基类的公有构造函数CPerson、成员函数SetNameAndSex和保护成员函数SetAge、ShowInfo。在派生类CStudent的构造函数的对象初始化列表中,就是通过调用基类的构造函数 CPerson(name,age,sex)对隐藏在派生类CStudent中的基类私有数据成员进行初始化。除此之外,派生类CStudent中的公有成员函数ShowAll中还调用了基类CPerson的保护成员函数ShowInfo。表1.1列出了派生类CStudent的所有成员及其访问权限。(3)在main函数中,A语句是调用派生类CStudent的构造函数对one对象进行初始化,由于CStudent的构造函数还调用了基类CPerson的构造函数,因而使派生类CStudent对象one的数据成员name、age、sex和stu

    注意事项

    本文(第1章C++基础1.ppt)为本站会员(hyn****60)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开