第四章类及对象_第1页
第四章类及对象_第2页
第四章类及对象_第3页
第四章类及对象_第4页
第四章类及对象_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

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

文档简介

C++程序设计宋存利类及对象

第四章类及对象

知识点:类与结构体类的声明与实现的分离构造函数析构函数

类中的常量const类中的静态static友元friendthis指针4.1类与结构体C语言中,结构体用来封装数据,利用结构体,程序员可构造复杂的数据结构如链表、树等。C++对C语言的结构体进行了扩展,结构体中也可以封装操作,也就是函数。

【例4-1】本题目要求对日期型数据进行处理,要求能输出一个日期,判断日期是否为闰年等.(1)C的方式fourth_1.cpp(2)结构体中封装数据和函数fourth_1_1.cpp4.1.2访问权限控制符public:用来标明从这儿开始直到遇到下一个不同的访问控制符为止,这中间定义的成员是公有的,也就是对外公开的一部分,这部分即可在结构体(类)中访问,也可在结构体(类)外通过对象进行访问。结构体中若没有设置成员的访问权限,则C++默认是公有的。private:用来标明从这儿开始直到遇到下一个不同的访问控制符为止,这中间定义的成员是私有的,也就是对外隐藏的,这部分成员只可在结构体(类)中访问。不能通过结构体变量(对象)进行访问。类中若没有设置成员的访问权限,则C++默认是私有的。protected:该标识符的作用在单个结构体(类)中意义和private一样。区别在于继承时protected访问权限的成员更容易被结构体(类)的子类继承。fourth_1_2.cpp(增加了访问权限的结构体)4.1.3类与对象类是对一批具有相同属性和动作的事物的描述。其中属性用数据来描述,动作用函数实现。类定义的一般格式为:class标识符{//数据成员//成员函数

};【例4-1】C++中的类是从结构体扩展而来。例如将fourth_1_2.cpp源文件中的结构体Date的定义拿来,更换关键字struct为class后,类Date的定义就完成了。

Fourth_1_3.cpp说明:类中成员的默认访问权限是private,结构体中成员的默认访问权限是public。4.1.3类与对象对象是类的实例化。定义对象的语法一般为:

类名

对象1,对象2,...;【例4-2】编写程序,功能实现求长方形的周长和面积。fourth_2.cpp说明:1.类的声明和结构体的声明相同,只需要将结构体关键字struct改为class。2.类是用户自定义类型。类一般并不能直接解决问题,要解决问题,必须创建具体对象,通过具体对象来解决问题。3.在同一个类中,访问权限控制符private、protected和public的出现次数、出现顺序没有限制。4.经验而谈,数据成员一般是需要隐藏的部分,成员函数一般是公开的部分,但还需设计者根据设计意图来确定。5.类的数据成员不仅可以是系统提供的内置类型,还可以是数组、指针、引用、也可以是另一个类定义的对象、指向对象的指针等。但不能是自身类型的对象,同时数据成员也不能指定其存储类型为auto、register、和外部extern类型。6.在定义类时,不能同时为数据成员赋值,但请注意C++11标准取消了这条限制,现在高版本的C++编译器基本允许,但为了程序的可移植性,建议不要这样做。7.类的成员之间可以互相访问。但在类外可访问类的公有成员,共有两种方法:1.类的对象通过成员运算符“.”来访问公有成员。例如:Rectanglerec;rec.setLength(3);//访问公有成员setLength函数rec.length=3;//错误的,不能访问私有成员2.通过指向对象的指针访问公有成员,用“->”运算符来访问,例如:Rectangle*p=newRectangle;p->setLength(3);//公有成员setLength函数(*p).setWidth(4);//*p代表p指向的对象p->length=3;//错误,不能访问私有成员

8.同结构体变量相同,对象占用的存储空间为其所有数据成员占用内存空间的和。

4.2类的声明与实现的分离成员函数(memberfunction)是类所抽象的事物具有的操作,成员函数的定义有两种方法:一种是在类内部直接定义;fourth_3_1.cpp另一种是在类内部进行声明,在类的外部进行定义。Fourth_3_2.cpp类的声明与实现分离案例fourth_4.cpp说明:1.在类的外部定义成员函数时,一定要加作用域“::”说明。用来说明该函数是那个类的成员。否则编译器会把相应的函数当成全局范围的普通函数处理。2.类内部实现的成员函数自动是内联函数。类外部定义的成员函数不会自动当成内联函数。3.类的成员函数可以重载,具体重载的要求可参考3.2节,此处不再举例。4.3构造函数

在创建对象时,编译器都会调用一个特殊的函数来对完成该对象的初始化操作,这个函数就是构造函数(constructorfunction)。

构造函数的功能主要是完成对象的初始化操作,当类的设计者在定义类时没有定义构造函数,系统会提供一个默认的构造函数,该默认构造函数的形式为:

类名(){}因系统提供的默认构造函数函数体是空的,因此并没有完成对象的初始化操作。要完成具体的初始化操作,类的设计者必须自己定义构造函数。4.3构造函数首先说明构造函数的特点:构造函数是个特殊的函数,它的名称和类名相同,且不能有返回值说明,他是在定义对象时由系统自动调用,用户不能调用。构造函数的功能是初始化对象。一个对象在其一生中一定会被构造一次且只构造一次,这就是在创建时。构造函数可以重载。构造函数不能由用户调用,只能在创建对象时由系统自动调用。当类的设计者没有定义构造函数时,系统会提供一个默认构造函数,他的形式是:

类名(){}//此构造函数不做什么操作4.3构造函数【例4-5】采用面向对象编程思想,求解立方体的体积、表面积,同时锻炼构造函数的编写。不定义构造函数的类fourth_5_1.cpp定义默认构造函数的类fourth_5_2.cpp提示:无参的构造函数系统也称为默认构造函数(defaultconstructor)。定义带参数的构造函数的类fourth_5_3.cpp构造函数可以重载【例4-6】Fourth_6.cpp说明注意:类名后之间传参数可创建无名对象。例如在【例4-6】中,按照Date类的定义,下面定义对象的语句也是正确的。

Date(2000,8,2);

//correct类名后直接传参数将构造一个无名对象该语句创建了一个无名对象,因此会执行对应匹配的构造函数。说明:单独的一条定义无名对象的语句没有意义。4.3.3拷贝构造函数定义变量可以用另一个已经存在的变量赋值,定义一个对象时可不可以用另一个已经存在的对象赋值能?请运行下面案例的出结论:【例4-7】编写二维坐标中的点这个类,用一个已经存在的点来创建。Fourth_7.cpp个点。g首先看案例,通过案例我们来找寻答案。4.3.3拷贝构造函数1.拷贝构造函数概念:拷贝构造函数是一个特殊的构造函数,它具有构造函数的一切特性,其特殊点在于拷贝构造函数只有一个参数,且它的参数类型是当前类的对象的引用。它的功能是用一个已经存在的对象来对新创建的对象赋初值。当类中没有定义拷贝构造函数时,系统会提供一个拷贝构造函数,其特点是用已经存在的对象的数据成员来对新创建的对象的对应数据成员赋值。2.拷贝构造函数定义的一般形式:

类名(当前类的类名&p){函数体}【例4-7】增加二维坐标点类的拷贝构造函数

Fourth_7_2.cpp请运行该程序,发现结果与fourth_7.cpp的结果的不同并总结3.拷贝构造函数的执行时机(1)用一个已经存在的对象来创建一个新的对象时执行拷贝构造函数(这是最本质原因)。查看fourth_7_2.cpp(2)对象做函数的参数时,当调用函数时,系统将利用实参对象创建形参对象,执行拷贝构造函数。Fourth_8.cpp(3)当函数的返回值是对象时,执行return语句时系统将调用拷贝构造函数创建返回值。Fourth_9.cpp注意:用对象的引用做参数时,不执行拷贝构造函数。Fourth_8_1.cpp4.4析构函数

一个对象在创建时系统除了要为他分配内存空间之外,还会自动调用执行构造函数,对其数据成员做初始化操作等。同样,当对象的生命周期到头时,需要释放其所占用的资源,包括内存空间。由系统分配的内存空间,系统会自动回收,但是用new分配的空间,在对象生命周期到头时系统不会自动回收。因此,必须通过一个特殊的函数来释放资源,这个特殊的函数就是析构函数。

同构造函数类似,析构函数也是类中一个特殊的函数,当程序员没有给出类的析构函数的定义时,系统会自动提供一个,只不过该析构函数什么也不做。系统提供的析构函数的形式为:

~类名(){}//空的函数体4.4析构函数析构函数的说明:析构函数是类中的一个特殊函数,他的名字和类名相同,但为了区别于构造函数,类名前有一个“~”符号。析构函数的功能释放对象占用的资源,例如存储空间。当类中没有析构函数时,系统会自动提供一个析构函数,其形式为:

~类名(){}析构函数没有参数,因此析构函数不能重载。析构函数在对象生命周期到头时由系统自动调用,用户无法显示调用析构函数,任何对象生命周期到头都要由系统自动调用其析构函数完成资源的回收。析构函数没有函数的返回值类型说明。4.4析构函数【例4-10】一个简单的关于析构函数的案例。Fourth_10.cpp注意:该案例中,类中的数据成员是普通类型,它们占用的内存资源是由系统自动分配的,系统在对象生命周期到头时会自动回收为其数据成员分配的内存资源。因此该案例中的析构函数只有一条输出语句,并没有回收资源的语句。在此处我们的目的是验证对象在生命周期到头时系统会自动调用析构函数,一般情况下象该案例中的析构函数是可以省略。【例4-11】涉及动态内存分配的情况,对Fourth_10.cpp的改造。请看Fourth_11.cpp【例4-12】该案例想要说明,当动态为对象的数据成员分配了内存资源时,除了要养成编写类的析构函数回收资源的习惯外,还需要要注意增加类的拷贝构造函数,否则程序会出现一些问题。Fourth_12.cpp增加了拷贝构造函数:Fourth_12_2.cpp,总结:总结:一般当一个类中有指针成员,涉及到动态内存分配,为了避免资源浪费,一般要定义类的析构函数,以便释放动态分配的资源。同时增加类的拷贝构造函数定义,在拷贝构造函数中为指针成员分配资源,避免一个对象的指针成员与其他对象的指针成员指向相同的空间,从而间接形成两个或多个对象的资源共享矛盾。4.5类中的常量const

在声明一个类时,关键字const也可用来说明类中的某个成员是常成员。因为类中的成员有两类(数据成员和成员函数),因此const与类中成员的结合也就有两种情况。const来修饰类中的某个数据成员是常数据成员;(1)类中常数据成员的声明方式为:const数据类型

常成员标识符;(2)在类中声明常数据成员时,不能同时对数据成员赋初值,这时必需提供构造函数且须在构造函数初始化列表中初始化常数据成员。(3)常数据成员的值只能被类的其他成员函数访问,不能修改。。(4)构造函数初始化列表案例fourth_14.cpp综合案例fourth_13.cpp构造函数初始化列表具体说明如下所示:

类名():构造函数初始化列表{构造函数体}

构造函数初始化列表的功能是对数据成员进行初始化操作,若对多个成员在此做初始化,则用逗号“,”隔开。但请注意:常数据成员只能在构造函数初始化列表中初始化,普通的数据成员即可在构造函数初始化列表中进行初始化操作,也可以在构造函数体中完成初始化。同时注意,拷贝构造函数对常成员的初始化也必需在构造函数初始化列表进行。4.5类中的常量const用const修饰类的成员函数。

在C++中,若类中的某个成员函数只对数据成员进行读操作,不进行写操作,则该成员函数就可以声明为常成员函数。这样做有什么好处呢?答案如下:(1)一个成员函数一旦声明成常成员函数,则编译器在编译时会自动帮你检查该函数中有没有修改数据成员的语句,若有,则提示出错,提高了程序的安全性。(2)常对象只能访问公有的常成员函数,若类中没有常成员函数,则常对象的功能就很有限了。常成员函数的声明格式:

返回值类型

函数名(参数列表)const;4.5类中的常量const2.用const修饰类的成员函数。(1)const是常成员函数的一部分,在声明和实现时都需要加关键字const。(2)const关键字也可以用于对重载函数的区分。(3)常成员函数不能更改任何数据成员的值,也不能调用该类中没有用const修饰的成员函数。(4)常对象只能访问类中公有的常成员。(5)只有类的成员函数才能声明或定义成常成员函数。【例4-15】常成员函数案例,fourth_15.cpp。4.6类中的静态static

在C++中,关键字static也可以出现在类中来修饰数据成员和成员函数,类中的某个成员若被static修饰,则该成员就是静态成员。静态成员将被类的所有对象共享,也就是说,无论用该类创建多少个对象,则静态成员的副本在内存中只有一份。1.类中静态数据成员的声明格式:

static数据类型

成员标识符;提示:在类中声明的静态数据成员不能直接赋初值,一般在类外部直接初始化。注意:【例4-16】静态数据成员案例,在该案例中,数据成员personcount用来统计在该程序中存在的人员数量。Fourth_16.cpp注意:类中的静态数据成员若为私有或受保护的,则不能在类外进行访问,只能在类的内部访问,方法和普通成员访问方式一样。若为公有数据成员,则即可在类内部象普通成员的访问方式一样,也可在类外部访问。类中static的公有数据成员在类外访问的方式有两种,分别为:(1)通过类名访问:

类名::静态数据成员(2)通过对象访问:

对象名.静态数据成员4.6类中的静态staticstatic成员函数类中静态成员函数的一般声明格式为:

static返回值类型函数名(参数列表);

如果把类中的某个成员函数声明为静态的,就可以把此函数与类的特定对象独立开来,该函数为类的静态成员函数。静态成员函数若为公有的,则即使在类对象不存在的情况下也能被调用,一般调用格式为:

类名::静态成员函数(实参列表);

当然也可通过该类的对象访问,方法为:

对象名.静态成员函数(实参列表);【例4-17】静态成员函数案例。加粗的函数为静态成员函数。Fourth_17.cpp4.7友元friend

类具有封装和信息隐藏的特性,但类的信息隐藏的特性使得类中的私有数据和受保护数据只能被类的成员函数访问,类之外的和其关系亲密的函数或另一个类不能访问,这在一定程度上造成了不同类的对象之间或对象与函数之间通信不便。这就好比你家特别要好的朋友,他没有你家的钥匙,在你家没人时,导致他去你家办事非常不方便。为了方便,我们一般的做法是给他一个去你家的通行证----钥匙,这样他就具有了访问你家所有资源的权限了,非常方便(有些人说,这很危险)。C++中为了解决这个问题,提出了友元机制,即通过将一个函数或一个类声明成另一个类的朋友,这个函数或类中的成员函数就具有了访问另一个类中所有成员的特权,包括私有和受保护的成员,从而达到方便通信的目的。4.7友元friend

如果将一个函数声明成一个类的朋友,则该函数就称为该类的友元函数。

若将类A声明成类B的朋友,则类A中的所有成员函数都是类B的友元函数,类A是类B的友元类。注意:(1)在C++中,友

温馨提示

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

评论

0/150

提交评论