第三章类和对象_第1页
第三章类和对象_第2页
第三章类和对象_第3页
第三章类和对象_第4页
第三章类和对象_第5页
已阅读5页,还剩81页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第三章类和对象第一页,共八十六页,2022年,8月28日第二页,共八十六页,2022年,8月28日第三页,共八十六页,2022年,8月28日 在C十十中,一个结构的成员通常分为两类:私有成员(private)和公有成员(public),私有成员(包括数据和函数)只能被该结构中的其它成员访问,而公有成员(包括数据和函数)既可被结构内其它成员访问,也可被结构外的其它部分访问。 例如在上例中,变量real和imag只需要被该结构的成员函数访问,则可声明为私有成员;四个成员函数需要在结构体外被调用,则可声明为公有成员。C十十规定,在缺省情况下,结构中的成员是公有的,因此上例结构complex中的成员都是公有的。第四页,共八十六页,2022年,8月28日第五页,共八十六页,2022年,8月28日2类的声明C十十提供了一种比结构类型更安全有效的数据类型——类。类是C十十的一个最重要的特性。类与结构的扩充形式十分相似,其一般形式如下:class

类名{private:

私有数据成员和成员函数

pubic:

公有数据成员和成员函数};

其中:class是声明类的关键字,类名是要声明的类的名字;后面的花括号表示出类的声明范围;最后的分号表示类声明结束。第六页,共八十六页,2022年,8月28日

类的声明内容包括数据和函数。类中的数据和函数都是类的成员,分别叫做数据成员和成员函数。

与结构的扩充形式一样。类的成员也分为私有成员和公有成员。私有成员用private说明,private下面的每一行,不论是数据成员还是成员函数,都是私有成员。私有成员只能被该类的成员函数访问,这是C十十实现封装的一种方法,即把特定的成员定义为私有的,就能严格地控制对它的访问。

公有成员用public说明,public下面的每一行都是公有成员。公有成员可被程序中的其它函数访问,它们是类的对外接口。第七页,共八十六页,2022年,8月28日

实际上,在C十十中,类class和结构struct是类似的.因为C十十的结构与类一样.都含有数据以及对这些数据进行的操作。它们的主要区别是缺省值不同:在类中,缺省时成员是私有的,而在结构中,缺省时成员是公有的。第八页,共八十六页,2022年,8月28日第九页,共八十六页,2022年,8月28日可以看出,类和结构的功能基本上相同。那么在C十十中为什么要用类代替结构呢?原因是,在缺省的情况下,类成员是私有的,类提供了缺省的安全性。这一规定符合面向对象思想中数据隐藏的准则。数据隐藏使得类中的成员比一般的局部变量得到更好的保护第十页,共八十六页,2022年,8月28日类的几点说明

(1)类的声明中的private和public两个关键字可以按任意顺序出现任意次。但是,如果把所有的私有成员和公有成员归类放在一起,程序将更加清晰。并且应该养成把所有的私有成员放在公有成员前面的习惯,因为一旦用户忘记了使用说明符private,由于缺省值是private,这将使用户的数据仍然得到保护。(2)除了private和public之外,类中的成员还可以用另一个关键字protected来说明。被protected说明的成员称为保护成员,它不能被外部函数使用,但可以通过其它方法使用它,将在第4章详细地介绍此方面内容。

第十一页,共八十六页,2022年,8月28日(3)数据成员可以是任何数据类型.但是不能用自动(auto)、寄存器(register)或外部(extern)进行说明。(4)不能在类的声明中给数据成员赋初值,C十十规定,只有在类对象定义之后才能给数据成员赋初值,例如:第十二页,共八十六页,2022年,8月28日成员函数的定义如上所述,类中含有两种成份,即数据成员和成员函数.其中成员函数也称方法。实际上,成员函数相方法指的是同一种实体,是一种实体的两种不同叫法,成员函数是程序设计语言c十十中的术语,而方法是面向对象方法中的术语。在以后的叙述中,本书采用术语成员函数。

成员函数的定义通常采用两种方式:第一种方式是在类声明中只给出成员函数的原型,而成员函数体在类的外部定义。这种成员函数定义的一般形式是:

返回类型类名::函数名(参数表){……….//函数体}第十三页,共八十六页,2022年,8月28日(1)在所定义的成员函数名之前应缀上类名,在类名和函数名之间加上分隔符“::”,例如上面例子中的“Point::”。(2)在定义成员函数时,对函数所带的参数,不但要说明它的类型,还要指出其参数名。(3)在定义成员函数时、其返回类型一定要与函数原型中声明的返回类型匹配。第十四页,共八十六页,2022年,8月28日第十五页,共八十六页,2022年,8月28日

将成员函数定义在类的内部,即定义为内置函数。在C++可以用下面两种格式定义类的内置函数:(1)隐式定义所谓内置函数的隐式定义,就是直接将函数定义在类内部,例如:成员函数的第二种定义方式第十六页,共八十六页,2022年,8月28日(2)显式定义在定义内置函数时,为了书写清晰,仍将它放在类定义体外。但为了使它仍然起内置函数的作用,在函数定义前冠以关键字“inline”,以此显式地说明这是一个内置函数。例如上面的例子改为显示定义可变成如下形式:第十七页,共八十六页,2022年,8月28日对象的定义及引用

1.类与对象的关系通常我们把具有同样性质和功能的东西所构成的集合称为类。在C十十中,可以把相同内部存储结构和相同操作集的对象看成属于同一类。在C十十中,对象是类的实际变量。类与对象间的关系,可以用整型int和整型变量i之间的关系来类比。类和整型int均代表的是一般的概念,而对象和整型变量i却是代表具体的东西。正像定义int类型的变量一样,也可以定义类的变量。C十十把类的变量称为类的对象,对象也称为类的实例。第十八页,共八十六页,2022年,8月28日

2.对象的定义定义对象的两种方法:(1)在声明类的同时,直接定义对象,即在声明类的右花括}后,直接写出属于该类的对象名称。例如:第十九页,共八十六页,2022年,8月28日(2)声明了类之后,在使用时再定义对象,定义的格式与一般变量的定义格式相同.如下所示:Pointop1,op2;此时定义了op1和op2为Point类的两个对象.第二十页,共八十六页,2022年,8月28日

3.对象的引用

对象的引用是指对对象成员的引用。不论是数据成员,还是成员函数.只要是公有的、就可以被外部函数直接引用,引用格式是:

对象名.数据成员名或

对象名.成员函数名(实参表)其中“.”叫做对象选择符,简称点运算符。第二十一页,共八十六页,2022年,8月28日第二十二页,共八十六页,2022年,8月28日第二十三页,共八十六页,2022年,8月28日几点说明(1)本例中opl.setpoint(1,2)实际上是一种缩写形式。它表达的意义opl.Point::setpoint(1,2),这两种表达式是等价的。(2)外部函数不能引用对象的私有成员。如果将例3.3中的主程序改成下面的形式第二十四页,共八十六页,2022年,8月28日则编译这个程序时,编译器将指示这两条语句的错误。这时可将这两条错误语句改成调用公有的成员函数来获得私有数据成员x和y的值.第二十五页,共八十六页,2022年,8月28日(3)在定义对象时.若我们定义的是指向此对象的指针,则访问此对象的成员时,不能用“.”操作符,而应使用“->”操作符,例如:

第二十六页,共八十六页,2022年,8月28日4.对象赋值语句

如果有两整型变量x和y,那么用y=x,就可以把x的值赋给y。同类型的对象之间也可以进行赋值.当一个对象赋值给另一个对象时,所有的数据成员都会逐位拷贝。例如,A和B是同一类的两个对象,假设A已经存在,那么下述对象赋值语句把对象A的值拷贝给对象B:B=A第二十七页,共八十六页,2022年,8月28日第二十八页,共八十六页,2022年,8月28日

说明

(1)在使用对象赋值语句进行对象赋值时,两个对象的类型必须相同,如对象的类型不同,编译时将出错。(2)两个对象之间的赋值,仅仅使这些对象中数据相同,而两个对象仍是分离的。例如本例对象赋值后、再调用o1.set()设置ol的值,不会影响o2的值。(3)将一个对象的值赋给另一个对象时,多数情况下都是成功的.但当类中存在指针时,可能会产生错误。这个问题我们将在第5章分析。第二十九页,共八十六页,2022年,8月28日3.1.4类的作用域

所谓类的作用域就是指在类的声明中的一对花括号所形成的作用域。一个类的所有成员都在该类的作用域内。一个类的任意成员可以引用该类的其它成员。C十十把类的所有成员都作为一个整体的相关部分。一个类的成员函数可以不受限制地引用该类的数据成员,而在该类作用域之外.对该类的数据成员和成员函数的引用则要受到一定的限制,有时甚至是不允许的。这体现了类的封装功能。下面的例子可帮助我们理解类的作用域。第三十页,共八十六页,2022年,8月28日第三十一页,共八十六页,2022年,8月28日3.2构造函数与析构函数3.2.1构造函数构造函数是一种特殊的成员函数.它主要用于为对象分配空间,进行初始化。构造函数具有一些特殊的性质:(1)构造函数的名字必须与类名相同(2)构造函数可以有任意类型的参数,但不能具有返回类型(3)定义对象时,编译系统会自动地调用构造函数。第三十二页,共八十六页,2022年,8月28日第三十三页,共八十六页,2022年,8月28日

构造函数不能像其它成员函数那样被显式地调用,它是在定义对象的同时调用的,其一般格式为:

类名

对象名(实参表),这里的“类名”与构造函数名相同,“实参表”是为构造函数提供的实际参数。第三十四页,共八十六页,2022年,8月28日第三十五页,共八十六页,2022年,8月28日第三十六页,共八十六页,2022年,8月28日第三十七页,共八十六页,2022年,8月28日构造函数的几点说明

(1)构造函数的名字必须与类名相同,否则编译程序将把它当作一般的成员函数来处理。(2)构造函数没有返回值,在声明和定义构造函数时,是不能说明它的类型的,甚至说明为void类型也不行。(3)在实际应用中,通常需要给每个类定义构造函数。如果没有给类定义构造函数,则编译系统自动地生成一个缺省的构造函数。(4)构造函数可以是不带参数第三十八页,共八十六页,2022年,8月28日此时,类ab的构造函数就没有带参数,在main()函数中可以采用如下方法定义对象:

abs;在定义对象s的同时,构造函数s.ab::ab()被系统自动调用执行幕上显示字符串“initialized”,并给私有数据成员a赋初值10。第三十九页,共八十六页,2022年,8月28日

(5)构造函数也可采用构造初始化表对数据成员进行初始化,这是某些程序员喜欢使用的方法。例如:第四十页,共八十六页,2022年,8月28日这个含有三个数据成员的类,利用构造初始表可以写成:第四十一页,共八十六页,2022年,8月28日

以上两种构造函数的定义都是有效的。但是如果需要将数据成员存放在堆中或数组中,则应在构造函数中使用赋值语句,即使构造函数有初始化表也应如此,例如:第四十二页,共八十六页,2022年,8月28日第四十三页,共八十六页,2022年,8月28日(6)对没有定义构造函数的类,其公有数据成员可以用初始值表进行初始化。请看以下例子。

在本例中,main()中创建了一个类myclass的对象a,并将初始值表中的“chen”和25分别赋给aname和a.no。程序运行结果为:chen25这种方法对结构和数组的初始化较适合。第四十四页,共八十六页,2022年,8月28日3.2.2缺省参数的构造函数

对于带参数的构造函数,在定义对象时必须给构造函数传递参数,否则构造函数将不被执行。但在实际使用中,有些构造函数的参数值通常是不变的,只有在特殊情况下才需要改变它的参数值,这时可以将其定义成带缺省参数的构造函数,例如:第四十五页,共八十六页,2022年,8月28日第四十六页,共八十六页,2022年,8月28日第四十七页,共八十六页,2022年,8月28日第四十八页,共八十六页,2022年,8月28日

在上面定义了三个对象s1、s2和s3,它们都是合法的对象。由于传递参数的个数不同.使它们的私有数据成员real相imag取得不同的值。

由于定义对象S1时,没有传递参数.所以real和imag均取构造函数的缺省值为其赋值Pg此real和imag均为0.0。

在定义对象s2时,只传递了一个参数,这个参数传递给构造函数的第一个参量,而第二个参量取缺省值,所以对象s2的real取值为1.1,而imag取值为0.0。在定义对象S3时,传递了两个参数,这两个参数分别传给了real和imag此real取值为1.1,imag取值为2.2。第四十九页,共八十六页,2022年,8月28日3.2.3析构函数析构函数也是一种特殊的成员函数。它执行与构造函数相反的操作,通常用于执行一些清理任务,如释放分配给对象的内存空间等。析构函数有以下一些特点:(1)析构函数与构造函数名字相同,但它前面必须加一个波浪号(~)。(2)析构函数没有参数,也没有返回值,而且不能重载,因此在一个类中只能有一个析构函数。(3)当撤消对象时,编译系统会自动地调用析构函数。第五十页,共八十六页,2022年,8月28日第五十一页,共八十六页,2022年,8月28日第五十二页,共八十六页,2022年,8月28日说明:每个类必须有一个析构函数。若没有显式地为一个类定义析构函数,编译系统会自动地生成一个缺省的析构函数。例如,编译系统为类complex生成缺省的构造函数如:

complex::~complex(){}第五十三页,共八十六页,2022年,8月28日对于大多数类而言,缺省的析构函数就能满足要求。但是,如果在一个对象完成其操作之前需要做一些内部处理,则应该显式地定义祈构函数,例如:

这是构造函数相析构函数常见的用法.即在构造函数中用运算符new为字符串分配存储空间,最后在析构函数中用运算符delete释放已分配的存储空间。第五十四页,共八十六页,2022年,8月28日3.2.4重载构造函数与一般的成员函数一样,C十十允许重载构造函数.以适应不同的场合。这些构造函数之间以它们所带参数的个数或类型的不同而区分。第五十五页,共八十六页,2022年,8月28日第五十六页,共八十六页,2022年,8月28日第五十七页,共八十六页,2022年,8月28日第五十八页,共八十六页,2022年,8月28日 这是一个计时器的例子。首先定义一个timer类,在创建对象时就赋给对象一个初始时间值。本例中,通过重载构造函数使用户可以用一个整数表示初始的秒数;也可用数字串或是指明时间为分、秒的两个整数表示初始的秒数。还可以不带参数.使初始值为零。第五十九页,共八十六页,2022年,8月28日说明:在重载没有参数和带缺省参数的构造函数时,有可能产生二义性,例如第六十页,共八十六页,2022年,8月28日 拷贝构造函数是一种特殊的构造函数。它用于依据已存在的对象建立一个新对象。典型的情况是,将参数代表的对象逐域拷贝到新创建的对象中。1.自定义拷贝构造函数自定义拷贝构造函数的一般形式如下:classname(constclass_name&b)//拷贝构造函数的函数体3.2.5拷贝构造函数第六十一页,共八十六页,2022年,8月28日 本例除了显式调用拷贝构造函数外,还可以采用赋值形式调用拷贝构造函数。第六十二页,共八十六页,2022年,8月28日

在定义对象p2时,虽然从形式上看是将对象pl赋值给了对象p2,但实际上调用的是拷贝构造函数,在对象p2被创建时,将对象pl的值逐域拷贝给对象p2,运行结果同上。第六十三页,共八十六页,2022年,8月28日

2.缺省的拷贝构造函数如果没有编写自定义的拷贝构造函数.c十十会自动地将一个已存在的对象复制给新对象,这种按成员逐一复制的过程是由缺省拷贝构造函数自动完成的。第六十四页,共八十六页,2022年,8月28日

3.3对象数组与对象指针

对象数组是指每一数组元素都是对象的数组.也就是说,若一个类有若干个对象就把这一系列的对象用一个数组来存放。类exam中没有自定义的构造函数,对象数组由C++的系统缺省构造函数建立。在赋值之前,每个对象数组元素都含有未定义的数据。第六十五页,共八十六页,2022年,8月28日第六十六页,共八十六页,2022年,8月28日如果类中含有用户定义的构造函数,而且构造函数带有参数,则定义对象数组时,可通过初始值表进行赋值。请看下面的例子。第六十七页,共八十六页,2022年,8月28日 若类中有构造函数,那么定义对象数组时,也可通过不带参数的构造函数或带有缺省参数的构造函数给对象数组元素赋值第六十八页,共八十六页,2022年,8月28日第六十九页,共八十六页,2022年,8月28日第七十页,共八十六页,2022年,8月28日3.3.2对象指针在c语言中能够直接访问结构,或通过指向该结构的指针来访问结构。类似地,在c十十语言中可以直接引用对象,也可以通过指向该对象的指针引用对象。对象指针是C十十的重要特性之一。

1.用指针引用单个对象成员说明对象指针的语法和说明其它数据类型指针的语法相同。使用对象指针时,首先要把它指向一个已创建的对象,然后才能引用该对象的成员。在一般情况下,用点运算符(.)来引用对象成员,当用指向对象的指针来引用对象成员时,就要用“->”操作符。第七十一页,共八十六页,2022年,8月28日第七十二页,共八十六页,2022年,8月28日2.用对象指针引用对象数组

对象指针不仅能引用单个对象,也能引用对象数组。下面的语句声明了一个对象指针和一个有两个元素的对象数组;exe*p//声明对象指针pexeob[3]//声明对象数组ob[3];若只有数组名,没有下标,这时该数组名代表第一个元素的地址p=ob;就把对象数组的第一个元素的地址赋给对象指针p。例如:第七十三页,共八十六页,2022年,8月28日

一般而言,当指针加1或减l时,它总是指向其基本类型中相邻的一个元素,对象指针也是如此。本例中指针对象p++时,指向下一个数组元素。第七十四页,共八十六页,2022年,8月28日指向类的非静态成员指针声明指向公有数据成员的指针:

类型说明符类名::*指针名;声明指向公有成员函数的指针类型说明符(类名::*指针名)(参数表);对数据成员指针赋值的一般语法形式:

指针名=&类名::数据成员;访问(调用)数据成员:对象名.*类成员指针名或对象指针名->*类成员指针名第七十五页,共八十六页,2022年,8月28日声明指向公有成员函数的指针类型说明符(类名::*指针名)(参数表);成员函数赋值:指针名=类名::成员函数名;访问(调用)成员函数:对象名.*类成员指针名(参数表)或对象指针名->*类成员指针名(参数表)

注意

成员函数指针的声明、赋值和使用过程中的返回值类型、函数参数表一定要匹配第七十六页,共八十六页,2022年,8月28日3.3.3this指针

C十十提供了一个特殊的对象指针——this指针。它是成员函数所属对象的指针。它指向类对象的地址。成员函数通过这个指针可以知道自己属于哪一个对象。this指针是一种隐含指针,它隐含于每个类的成员函

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论