C++程序设计 第9章 类和对象

上传人:公**** 文档编号:569166288 上传时间:2024-07-27 格式:PPT 页数:273 大小:2.22MB
返回 下载 相关 举报
C++程序设计 第9章 类和对象_第1页
第1页 / 共273页
C++程序设计 第9章 类和对象_第2页
第2页 / 共273页
C++程序设计 第9章 类和对象_第3页
第3页 / 共273页
C++程序设计 第9章 类和对象_第4页
第4页 / 共273页
C++程序设计 第9章 类和对象_第5页
第5页 / 共273页
点击查看更多>>
资源描述

《C++程序设计 第9章 类和对象》由会员分享,可在线阅读,更多相关《C++程序设计 第9章 类和对象(273页珍藏版)》请在金锄头文库上搜索。

1、第九章第九章 类和对象类和对象第9章 类和对象9.1 面向对象的程序 设计方法概述9.2 类和对象 9.3 类对象 9.4 构造函数和析构 函数9.5 类的初始化 9.6 静态成员及静态成员函数9.7 内联成员函数9.8 复杂的对象表示 9.9 堆9.10 this指针 9.11 常类型 9.12 友元概述n面向过程的设计方法n面向对象的方法回顾:面向过程的设计方法n重点:n如何实现的细节和过程,将数据与函数分开。n形式:n主模块+若干个子模块(main()+子函数)。n特点:n自顶向下,逐步求精功能分解。n缺点:n效率低,程序的可重用性差。面向对象的方法n目的:n实现软件设计的产业化。n观点

2、:n自然界是由实体(对象)所组成。n程序设计方法:n使用面向对象的观点来描述模仿并处理现实问题。n要求:n高度概括、分类、和抽象。几个特性n类(Class)是面向对象程序设计(OOP)实现信息封装的基础。n抽象是对具体对象(问题)进行概括,抽出这一类对象的公共性质并加以描述的过程。n将抽象出的数据成员、代码成员相结合,将它们视为一个整体。n继承与派生n多态n重载函数和虚函数几点几点几点几点如何调整如何调整如何调整如何调整通信通信通信通信构造构造构造构造class钟private:钟的构造;public:读取时间值读取时间值;调整时间值调整时间值;举例举例举例举例9.2 类和对象n对象(Obje

3、ct)是现实世界中的客观事物。n类是把具有相同属性的事物划分为一类,从而得出的抽象概念。n类概括了一组对象共同性质的数据和函数组成。n面向对象的程序设计中最基本的概念是对象,n是一个实体的实例,其包括了特定的数据和对这些数据进行操作的函数。n对象的核心概念:n“封装性”(encapsulation)n“继承性”(inheritance)n“多态性”(polymorphism)。 9.2.1 9.2.1 类的定义类的定义类是一种用户自定义的数据类型,它的一般定义格式如下(以前的传统用法):class class private private: ; protectedprotected: ; p

4、ublicpublic: ; ; 或者: class 类名 private: 私有的数据和成员函数; public: 公有的数据和成员函数; 说明nclass是定义类的关键字。n是一个标识符,用于唯一标识一个类。n类的说明部分,说明该类的所有成员。n类的成员包括数据成员和成员函数两部分。n类的成员从访问权限上分有以下三类:n公有的(public)n私有的(private)n保护的(protected)n其中默认为private权限。n公有的成员(public)n可以被程序中的任何代码访问;n私有的成员(private)n只能被类本身的成员函数及友元类的成员函数访问,其他类的成员函数,包括其派生

5、类的成员函数都不能访问它们;n保护的成员(protected)n与私有成员类似,只是除了类本身的成员函数和说明为友元类的成员函数可以访问保护成员外,该类的派生类的成员也可以访问。说明:n类的定义不一定都包括:private和public 部分,可以只含private部分或public部分。nprivate部分或public部分可以出现多次nprivate部分和public部分次序任意例9-1:include class Sample int x,y;public:Sample() x=y=0;Sample(int a,int b) x=a;y=b;Void disp() cout”x=”x”,

6、y=”yendl;void main()Sample s1,s2(1,2);s1.disp();s2.disp();此程序的运行结果为:x=0,y=0x=1,y=2 保护部分数据成员的目的在于将它们有效地屏蔽,以防外界的干扰和误操作,增强适应性。例 定义时间类(Time)。实例实例 分析:Time包括以下属性和操作: 属性,时间值,包括:时(hour)、 分(minute)、秒(second)。 操作,设置时间(SetTime);显示时间(分为12小时制(DisplayTime12)和24小时制(DisplayTime24)两种显示方式。classTimeprivate:inthour;/0-

7、23intminute;/0-59intminute;/0-59public:Time();/构造函数构造函数voidSetTime(int,int,int);voidDisplayTime12(void);voidDisplayTime24(void);9.2.2 9.2.2 类的成员函数类的成员函数定义类的函数成员的格式如下:返回类型返回类型 类名类名:成员函数名(参数说明)成员函数名(参数说明) 函数体函数体 类的成员函数对类的数据成员进行操作,成员函数的定义体可以在类的定义体中,如例9-2所示。 n与普通的函数的区别是:属于一个类的成员,出现在类体中。n需要被外界调用的定义为publi

8、c,它是类对外接口成员函数的定义形式:n在类内定义成员函数;n在类外定义成员函数在类内定义成员函数class studentclass student public :public : void display() void display() cout cout “num:num:”numendl;numendl; cout cout “name:name:”nameendl;nameendl; cout cout “sex:sex:”sexendl;sexendl; private:private: int num; int num; char name20; char name20; c

9、har sex; char sex;n如果成员函数的规模较小(代码较短,包含15个语句),一般都在类内部直接定义该函数,例如上面的例子中的set函数就是在Tdate类中直接定义的。 n例9-2 定义日期类(Tdate),并处理闰年问题。 定义类和对象定义类和对象 / 例例 一个类的例子一个类的例子#includeclassTdatepublic:voidSet(intm,intd,inty)month=m;day=d;year=y;intIsLeapYear()return(year%4=0&year%100!=0)|(year%400=0);voidPrint()coutyear.month

10、.dayendl;private:intmonth;intday;intyear;voidmain()Tdatea;a.Set(10,16,2003);a.Print(); 定义类和对象定义类和对象 /一个类的例子#includeclassTdatepublic:voidSet(intm,intd,inty)month=m;day=d;year=y;intIsLeapYear()return(year%4=0&year%100!=0)|(year%400=0);voidPrint()coutyear.month.dayendl;private:intmonth;intday;intyear;v

11、oidmain()Tdatea;a.Set(10,16,2003);a.Print(); 定义类和对象定义类和对象 /例一个类的例子#includeclassTdatepublic:voidSet(intm,intd,inty)month=m;day=d;year=y;intIsLeapYear()return(year%4=0&year%100!=0)|(year%400=0);voidPrint()coutyear.month.dayendl;private:intmonth;intday;intyear;voidmain()Tdatea;a.Set(10,16,2003);a.Print

12、();关键字关键字定义一个类定义一个类标识符标识符类名类名classclass ,structstruct,unionunion都可以定义一个类:都可以定义一个类:都可以定义一个类:都可以定义一个类:classclass缺省说明时,其成员被认为缺省说明时,其成员被认为缺省说明时,其成员被认为缺省说明时,其成员被认为是私有的是私有的是私有的是私有的structstruct若不特别指出,其所有成员若不特别指出,其所有成员若不特别指出,其所有成员若不特别指出,其所有成员都是公有的都是公有的都是公有的都是公有的unionunion其所有成员都是公有的,且其所有成员都是公有的,且其所有成员都是公有的,且

13、其所有成员都是公有的,且不能更改不能更改不能更改不能更改 定义类和对象定义类和对象 / 例例 一个类的例子一个类的例子#includeclassTdatepublic:voidSet(intm,intd,inty)month=m;day=d;year=y;intIsLeapYear()return(year%4=0&year%100!=0)|(year%400=0);voidPrint()coutyear.month.dayendl;private:intmonth;intday;intyear;voidmain()Tdatea a;a.Set(10,16,2003);a.Print();a

14、aTdate类型的一个类型的一个对象(实例)对象(实例) 定义类和对象定义类和对象 / 一个类的例子一个类的例子#includeclassTdatepublic:voidSet(intm,intd,inty)month=m;day=d;year=y;intIsLeapYear()return(year%4=0&year%100!=0)|(year%400=0);voidPrint()coutyear.month.dayendl;private:intmonth;intday;intyear;voidmain()Tdatea;a.Set(10,16,2003);a.Print(); 定义类和对象

15、定义类和对象 / 例例 一个类的例子一个类的例子#includeclassTdatepublic:voidSet(intm,intd,inty)month=m;day=d;year=y;intIsLeapYear()return(year%4=0&year%100!=0)|(year%400=0);voidPrint()coutyear.month.dayendl;private:intmonth;intday;intyear;voidmain()Tdatea;a.Set(10,16,2003);a.Print();数据成员数据成员 定义类和对象定义类和对象 / 例例 一个类的例子一个类的例子

16、#includeclassTdatepublic:voidSet(intm,intd,inty)month=m;day=d;year=y;intIsLeapYear()return(year%4=0&year%100!=0)|(year%400=0);voidPrint()coutyear.month.dayendl;private:intmonth;intday;intyear;voidmain()Tdatea;a.Set(10,16,2003);a.Print();类中定义成员函数类中定义成员函数内联函数处理内联函数处理在类的外部定义成员函数在类的外部定义成员函数 在定义类时,C+的习惯做

17、法是:类接口和类的源代码分离。 这种分离方式符合软件工程的基本原则。 (1)将类的定义(属性定义和部分内联成员函数的声明)放在一个头文件(*.h)中,该文件可以被任何使用该类的程序用include命令所包含形成类的接口。 (2)该类的大多数成员函数则在源程序文件(*.cpp)中声明,并在类的接口中保留成员函数的原型。 注意:尽管成员函数的定义与类体分离,但这些函数还是属于某一个类的。 成员函数的标记成员函数的标记 为了与非成员函数区别,在定义成员函数时切记在函数名前面加上类名和作用域区分符: : 例 将例9-2 中的Tdate类的成员函数改成在Tdate类之外定义。 (1)将Tdate类的定义

18、存放在头文件Tdate.h中 class Tdate /数据成员声明 private: int month, day, year; /成员函数声明(原型) public: void set(int ,int ,int); /设置日期 int IsLeapYear(); /判断是否为闰年 void Print(); /输出日期; (2)Tdate类的源程序类的源程序 #include#includeTdate.h/*/成员函数set*/*voidTdate:set(intm,intd,inty)month=m;day=d;year=y;/将存放Tdate定义的头文件包含进来/设置日期源程序(源程

19、序(Tdate.cpp)如下:如下: /*/*成员函数成员函数IsleapYear *IsleapYear *int int Tdate:Tdate:IsLeapYear( )IsLeapYear( ) if (year %4 =0 & year % 100!=0) if (year %4 =0 & year % 100!=0) return(1); return(1); else else if (year % 400 =0) if (year % 400 =0) return(1); return(1); else else return(0); return(0); /*/*成员函数成员

20、函数Print*Print*void void Tdate:Tdate:Print( )Print( ) cout month / day / year endl; cout month / day / year endl; ; /判断是否为闰年/输出日期(3)使用)使用Tdate类的源程序类的源程序 p1.cpp#include#include“Tdate.h”voidmain()Tdatedate;intmonth,day,year;coutmonthdayyear;date.set(month,day,year);date.Print();if(date.IsLeapYear()cout

21、闰年闰年;elsecout不是闰年不是闰年;/用Tdate类声明日期对象date/调用Tdate类的成员函数几点说明几点说明 Tdate类由存放类体(类接口)的Tdate.h文件和存放类成员函数源代码的Tdate.cpp文件组成。 存放在Tdate头文件中的Tdate类可供其它程序引用。 我们可以把类定义(头文件)看成是类的外部接口,类的成员函数定义看成是类的内部实现。 本程序使用了Tdate类,从结构上来看,包含三个源文件P1.cpp、Tdate.cpp、Tdate.h。属于多文件结构。各个.cpp的文件独立编译成.obj文件,并加入到项目中,连接程序(Bulid)会自动将它们连接成一个可执

22、行文件.exe。例9-3:类中的成员函数在类定义中直接描述示例。classLocationpublic:voidinit(intx,inty)X=x;Y=y;private:intX,Y;public:intGetX()returnX;intGetY()returnY;类类的的成成员员函函数数也也可可以以另另外外定定义义,而而在在类类定定义义时时给给出函数头。出函数头。例9-3 的成员函数可说明如下:void Location:init(int x,int y) X=x; Y=y;/将x,y的值分别赋给X,Yint Location:GetX() return X;intLocation:Ge

23、tY()returnY;9.1.3 9.1.3 类和和结构的区构的区别结构是类的一种特例,在结构中也可以定义成员函数。定义结构时只要把关键字class 改为struct即可。class Location private: int X,Y;public: void init(int x,int y) X=x; Y=y; intGetX()returnX;intGetY()returnY;结构和类的唯一区别是:在未指定访问权限时,结构中的成员被默认为公有的而类中的成员被默认为私有的。在所有其他方面,类和结构等价。例如:structSintX;/公有的.classCintX;/私有的. 尽管类和结构

24、是等价的,但一般在描述数据时使用结构,在描述数据及对数据的操作时用类。9.3 类对象为了使用类,还必须说明类的对象。在定义类时,系统是不会给类分配存储空间的,只有定义类对象时才会给对象分配相应的内存空间。9.3.1 9.3.1 对象的定义格式对象的定义格式定义类对象的格式如下: ; 例如:例如:Tdate t;Tdate t;n中可以有一个或多个对象名,多个对象名用逗号分隔n在中,可以是一般的对象名,还可以是指向对象的指针名或引用名,也可以是对象数组名。 对象n定义对象的方法定义对象的方法n先声明类类型,然后再定义对象n在声名类类型的同时定义对象n不出现类名,直接定义对象先声明类类型,然后再定

25、义对象class studentclass student public :public : void display() void display() cout cout “num:num:”numendl;numendl; cout cout “name:name:”nameendl;nameendl; cout cout “sex:sex:”sexendl;sexendl; private:private: int num; int num; char name20; char name20; char sex; char sex; student stud1,stud2; studen

26、t stud1,stud2; 或或 class student stud1,stud2;class student stud1,stud2;在声名类类型的同时定义对象class studentpublic : void display() cout “num:”numendl; cout “name:”nameendl; cout “sex:”sexendl; private: int num; char name20; char sex;stud1,sdud2;不出现类名,直接定义对象class public : void display() cout “num:”numendl; cout

27、 “name:”nameendl; cout “sex:”sexendl; private: int num; char name20; char sex;stud1,sdud2;例如:银行账目举例。Savings 类的主要属性有:帐号、余额等。Savings 类的主要操作有:存款、取款、查询余额等。class Savings private: unsigned accountNo; /帐号 float balance; /余额 public: deposit (unsigned amount) balance += amount; return balance; ;/成员函数本例只给出存款函

28、数/*include“Tsavings.h”voidmain()Savingss1,s2;s1.deposit(100.5);s2.deposit(200.5);classSavingsprivate:unsignedaccountNo;floatbalance;public:deposit(unsignedamount)balance+=amount;returnbalance;/声明对象/调用类的操作(成员函数)9.3.2 9.3.2 对象成员的表示方法对象成员的表示方法一个对象的成员就是该对象的类所定义的成员。对象成员有数据成员和成员函数。一般对象的成员表示如下: . 或者 . ( )前

29、者用于表示数据成员,后者用于表示成员函数。这里的“.”是一个运算符,该运算符的功能是表示对象的成员。#include#includeusing namespace std;using namespace std;class Clockclass Clock ./ ./类的声明略的声明略 /./.类的的实现略略int main()int main() Clock myClock; Clock myClock; myClock.SetTime(8,30,30); myClock.SetTime(8,30,30); myClock.ShowTime(); myClock.ShowTime(); 指向

30、对象的指针的成员表示如下: - 或者 - ( )n “-”用来表示指向对象的指针的成员n“.”用来表示一般对象的成员。 对于数据成员和成员函数,以下两种表示方式是等价的: - 与(* * ). class Time public: int hour; int minute;Time t,*p;p=&t;couthour;p-hourp-hour(*p).hour(*p).hourt.hourt.hour三者等价三者等价公有成员是提供给外部的接口类外用“.”和“-”运算符访问对象成员 访问对象成员访问对象成员 公有成员是提供给外部的接口类外用“.”和“-”运算符访问对象成员 访问对象成员访问对象

31、成员 访问访问公有数据成员公有数据成员公有成员是提供给外部的接口类外用“.”和“-”运算符访问对象成员 访问对象成员访问对象成员 调用调用公有成员函数公有成员函数公有成员是提供给外部的接口类外用“.”和“-”运算符访问对象成员对象使用“.”,指针使用“-”来访问对象成员。 访问对象成员访问对象成员 公有成员是提供给外部的接口类外用“.”和“-”运算符访问对象成员 访问对象成员访问对象成员 建立建立动态对象动态对象公有成员是提供给外部的接口类外用“.”和“-”运算符访问对象成员 访问对象成员访问对象成员 用指针用指针访问对象成员访问对象成员9.4 构造函数和析构函数n无论何时,创建对象时都要调用

32、构造函数(包括默认构造函数)。n构造函数的工作是建立对象的基本结构,进行数据初始化。n当一个对象退出其作用域时,都要调用析构函数。n析构函数的工作是:n执行析构函数中的代码;n将对象占据的存储空间归还系统;构造函数和析构函数都是类的成员函数,但它们是特殊的成员函数,不用调用便自动执行,而且这些函数的名字与类的名字有关。 9.4.1 构造函数构造函数的作用是:为对象分配空间;对数据成员赋初值;请求其他资源。构造函数n构造函数的作用是在对象被创建时使用特定的值构造对象,或者说将对象初始化为一个特定的状态。n在对象创建时由系统自动调用。n构造函数可以有任意类型的参数,但不能具有返回类型。n构造函数名

33、与类名相同n如果程序中未声明,则系统自动产生出一个默认形式的构造函数n允许为内联函数、重载函数、带默认形参值的函数如果一个类没有定义构造函数,编译器会自动生成一个不带参数的默认构造函数,其格式如下: : ()() 在程序中定义一个对象而没有指明初始化时,编译器便按默认构造函数来初始化该对象或或类名 : 类名 ( 参数表 );构造函数举例构造函数举例class Clockclass Clock public:public:Clock(int NewH,int NewM,int NewS);/Clock(int NewH,int NewM,int NewS);/构造函数构造函数void SetTi

34、me(int NewH,int NewM,int NewS);void SetTime(int NewH,int NewM,int NewS);void ShowTime();void ShowTime();private:private:int Hour,Minute,Second;int Hour,Minute,Second;构造函数的实现:构造函数的实现:Clock:Clock(int NewH, int NewM, int NewS)Clock:Clock(int NewH, int NewM, int NewS) Hour= NewH;Hour= NewH;Minute= NewM;

35、Minute= NewM;Second= NewS;Second= NewS; 建立对象时构造函数的作用:建立对象时构造函数的作用:int main()int main() Clock c(0,0,0); Clock c(0,0,0); /隐含含调用构造函数,将初始用构造函数,将初始值作作为实参。参。 c.ShowTime();c.ShowTime(); 64例 定义一个Desk类,该类包含有构造函数,用来初始化Desk对象。 (1) 分析 Desk类的主要属性有:重量、长度、高度以及宽度等。 Desk类的主要操作有:构造函数(用来对实例对象进行初始化)、Display等。 (2 2)Desk

36、Desk类的定义及引用类的定义及引用 #includeclassDeskprotected:intweight,high,width,length;public:Desk()weight=10;high=5;width=5;length=5;/Desk类的构造函数voiddisplay()cout“weight:”weight“high:”high“width:”width“length:”length;/其它成员函数其它成员函数;voidmain()Deskdesk1;desk1.display();/声明声明desk1对象,此时构造函数自动工作对象,此时构造函数自动工作/调用调用desk对

37、象的对象的display成员函数成员函数。weight:10high:5width:5length:5运行结果:运行结果:(3 3)几点说明)几点说明 Desk1对象的各个数据成员的初始值是由构造函数Desk函数设置的。 Desk函数是自动调用的,而且构造函数名必须与类名相同。 注意: 一个类只能定义一个构造函数(但允许重载)。 带参数的构造函数在建立对象时,以特定的数据初始化 对象的数据成员9.4.2 9.4.2 带参数的构造函数带参数的构造函数 #includeclassDatepublic:Date(int,int,int);Date();voidSetDate(inty,intm,in

38、td);voidIsLeapYear(); voidPrintDate();private:intyear,month,day;Date:Date(inty,intm,intd)year=y;month=m;day=d;coutyear/month/day:Dateobjectinitialized.n;Date:Date()coutyear/month/day:Dateobjectdestroyed.n;voidDate:SetDate(inty,intm,intd)year=y;month=m;day=d;voidDate:IsLeapYear()if(year%4=0&year%100!

39、=0|year%400=0)coutyearIsleapyear.n;elsecoutIsnotleapyear.n;voidDate:PrintDate()coutyear/month/dayendl;voidmain()Dated1(2000,5,1);d1.PrintDate();d1.IsLeapYear();#includeclassDatepublic:Date(int,int,int);Date();voidSetDate(inty,intm,intd);voidIsLeapYear();voidPrintDate();private:intyear,month,day;Date

40、:Date(inty,intm,intd)year=y;month=m;day=d;coutyear/month/day:Dateobjectinitialized.n;Date:Date()coutyear/month/day:Dateobjectdestroyed.n;voidDate:SetDate(inty,intm,intd)year=y;month=m;day=d;voidDate:IsLeapYear()if(year%4=0&year%100!=0|year%400=0)coutyearIsleapyear.n;elsecoutIsnotleapyear.n;voidDate:

41、PrintDate()coutyear/month/dayendl;voidmain()Dated1(2000,5,1);d1.PrintDate();d1.IsLeapYear();Date(int,int,int);Date:Date(inty,intm,intd)/ 带参数构造函数带参数构造函数year=y;month=m;day=d;coutyear/month/day:Dateobjectinitialized.n;#includeclassDatepublic:Date(int,int,int);Date();voidSetDate(inty,intm,intd);voidIsLe

42、apYear(); voidPrintDate();private:intyear,month,day;Date:Date(inty,intm,intd)year=y;month=m;day=d;coutyear/month/day:Dateobjectinitialized.n;Date:Date()coutyear/month/day:Dateobjectdestroyed.n;voidDate:SetDate(inty,intm,intd)year=y;month=m;day=d;voidDate:IsLeapYear()if(year%4=0&year%100!=0|year%400=

43、0)coutyearIsleapyear.n;elsecoutIsnotleapyear.n;voidDate:PrintDate()coutyear/month/dayendl;voidmain()Dated1(2000,5,1);d1.PrintDate();d1.IsLeapYear();Date(int,int,int);Date:Date(inty,intm,intd)/ 带参数构造函数带参数构造函数year=y;month=m;day=d;year=y;month=m;day=d;coutyear/month/day:Dateobjectinitialized.n;用初始式用初始式

44、对数据成员置值对数据成员置值9.4.2 带参数的构造函数带参数的构造函数/例例 对象成员初始化对象成员初始化#includeclassApublic:A(intx):a(x)inta;classBpublic:B(intx,inty):aa(x),b(y)voidout()coutaa=aa.aendlb=bendl;private:intb;Aaa;voidmain()BobjB(3,5);objB.out();类类型数据成员类类型数据成员/例例 对象成员初始化对象成员初始化#includeclassApublic:A(intx):a(x)inta;classBpublic:B(intx,i

45、nty):aa(x),b(y)voidout()coutaa=aa.aendlb=bendl;private:intb;Aaa;voidmain()BobjB(3,5);objB.out();/例例 对象成员初始化对象成员初始化#includeclassApublic:A(intx):a(x)inta;classBpublic:B(intx,inty):aa(x),b(y)voidout()coutaa=aa.aendlb=bendl;private:intb;Aaa;voidmain()BobjB(3,5);objB.out();首先调用首先调用成员类构造函数成员类构造函数/例例 对象成员初

46、始化对象成员初始化#includeclassApublic:A(intx):a(x)inta;classBpublic:B(intx,inty):aa(x),b(y)voidout()coutaa=aa.aendlb=bendl;private:intb;Aaa;voidmain()BobjB(3,5);objB.out();3objB.aa.a3objB.aa.a/例例 对象成员初始化对象成员初始化#includeclassApublic:A(intx):a(x)inta;classBpublic:B(intx,inty):aa(x),b(y)voidout()coutaa=aa.aendl

47、b=bendl;private:intb;Aaa;voidmain()BobjB(3,5);objB.out();5objB.b再初始化再初始化自身数据成员自身数据成员3objB.aa.a/例例 对象成员初始化对象成员初始化#includeclassApublic:A(intx):a(x)inta;classBpublic:B(intx,inty):aa(x),b(y)voidout()coutaa=aa.aendlb=bendl;private:intb;Aaa;voidmain()BobjB(3,5);objB.out();5objB.b3objB.aa.a/例例 对象成员初始化对象成员初

48、始化#includeclassApublic:A(intx):a(x)inta;classBpublic:B(intx,inty):aa(x),b(y)voidout()coutaa=aa.aendlb=bendl;private:intb;Aaa;voidmain()BobjB(3,5);objB.out();5objB.b3objB.aa.a/例例 对象成员初始化对象成员初始化#includeclassApublic:A(intx):a(x)inta;classBpublic:B(intx,inty):aa(x),b(y)voidout()coutaa=aa.aendlb=bendl;pr

49、ivate:intb;Aaa;voidmain()BobjB(3,5);objB.out();5objB.b与一般函数一样,C+允许重载构造函数若类X具有一个或多个构造函数,创建类X的对象时,根据参数的类型和个数进行匹配9.4.3 重载构造函数重载构造函数9.4.3 9.4.3 重载构造函数重载构造函数例:例:classXpublic:X();X(int);X(int,char);X(double,char);.;voidf()Xa;Xb(1);Xc(1,c);Xd(2.3,d);.9.4.3 9.4.3 重载构造函数重载构造函数例:例:classXpublic:X ( ) ;X(int);X

50、(int,char);X(double,char);.;voidf()Xa;Xb(1);Xc(1,c);Xd(2.3,d);./ 调用构造函数调用构造函数 X()9.4.3 9.4.3 重载构造函数重载构造函数例:例:classXpublic:X();X( int ) ;X(int,char);X(double,char);.;voidf()Xa;X b ( 1 ) ;Xc(1,c);Xd(2.3,d);./ 调用构造函数调用构造函数 X(int)9.4.3 9.4.3 重载构造函数重载构造函数例:例:classXpublic:X();X(int);X ( int, char ) ;X(dou

51、ble,char);.;voidf()Xa;Xb(1);X c ( 1 , c ) ;Xd(2.3,d);./ 调用构造函数调用构造函数 X(int, char)9.4.3 9.4.3 重载构造函数重载构造函数例:例:classXpublic:X();X(int);X(int,char);X ( double, char ) ;.;voidf()Xa;Xb(1);Xc(1,c);X d ( 2.3 , d ) ;./ 调用构造函数调用构造函数 X(double, char)9.4.3 9.4.3 重载构造函数重载构造函数构造函数可以使用缺省参数,但谨防二义性例:例:classXpublic:X

52、();X(inti=0);.;voidmain()Xone(10);/ 正确正确.Xtwo;/ 二义性。二义性。调用调用 X:X(),还是,还是调用调用 X:X(int = 0) ?/例例 不同构造函数的匹配不同构造函数的匹配#includeclassTdatepublic:Tdate()month=10;day=1;year=2000;Tdate(intd)month=10;day=d;year=2000;Tdate(intm,intd)month=m;day=d;year=2000;Tdate(intm,intd,inty)month=m;day=d;year=y;voidprintDat

53、e()coutmonth/day/yearendl;protected:intmonth;intday;intyear;voidmain()Tdateaday;aday.printDate();Tdatebday(5);bday.printDate();Tdatecday(2,12);cday.printDate();Tdatedday(1,2,1998);dday.printDate();/例例 不同构造函数的匹配不同构造函数的匹配#includeclassTdatepublic:Tdate()month=10;day=1;year=2000;Tdate(intd)month=10;day=

54、d;year=2000;Tdate(intm,intd)month=m;day=d;year=2000;Tdate(intm,intd,inty)month=m;day=d;year=y;voidprintDate()coutmonth/day/yearendl;protected:intmonth;intday;intyear;voidmain()Tdateaday;aday.printDate();Tdatebday(5);bday.printDate();Tdatecday(2,12);cday.printDate();Tdatedday(1,2,1998);dday.printDate

55、();9.4.4 9.4.4 拷贝构造函数拷贝构造函数( (复制构造函数复制构造函数) )拷贝构造函数是一种特殊的构造函数,其形参为本类的对象引用。class 类名 public : 类名(形参);/构造函数 类名(类名 &对象名);/拷贝构造函数 .;类名:类(类名 &对象名)/拷贝构造函数的实现 函数体 复制构造函数用一个已有同类对象的数据对正在建立的对象进行数据初始化C+为类提供默认版本的复制构造函数程序员可以定义用户版本的复制构造函数语法形式类名:类名(const类名&引用名,); 复制构造函数复制构造函数保护实参对象保护实参对象只读只读classApublic:A(int);A(co

56、nstA&,int=1); Aa(1);Ab(a,0);Ac=b; 复制构造函数复制构造函数classApublic:A ( int ) ;A(constA&,int=1); Aa(1);Ab(a,0);Ac=b; 复制构造函数复制构造函数/ 构造函数构造函数classApublic:A(int);A ( const A &const A & , int =1 ) ; Aa(1);Ab(a,0);Ac=b; 复制构造函数复制构造函数/ 复制构造函数复制构造函数classApublic:A(int);A(constA&,int=1); Aa(1);Ab(a,0);Ac=b; 复制构造函数复制构造

57、函数/ 复制构造函数复制构造函数/ 创建对象创建对象 a,调用,调用 A (int) classApublic:A(int);A(constA&,int=1); Aa(1);Ab(a,0);Ac=b; 复制构造函数复制构造函数/ 复制构造函数复制构造函数/创建对象创建对象 b,调用,调用 A (const A & , int =1)classApublic:A(int);A(constA&,int=1); Aa(1);Ab(a,0);Ac=b; 复制构造函数复制构造函数/ 复制构造函数复制构造函数/创建对象创建对象 c,调用,调用 A (const A & , int =1)classApub

58、lic:A(int);A(constA&,int=1); Aa(1);Ab(a,0);Ab(a,0);Ac=b;Ac=b; 复制构造函数复制构造函数/ 复制构造函数复制构造函数/创建对象创建对象 c,调用,调用 A (const A & , int =1)/创建对象创建对象 b,调用,调用 A (const A & , int =1)/ 创建对象创建对象 a,调用,调用 A (int) 调用复制构造函数调用复制构造函数的两种典型方法的两种典型方法/例例 用已有对象初始化新创建对象用已有对象初始化新创建对象#includeclassLocationpublic:Location(intxx=0,

59、intyy=0)X=xx;Y=yy;Location(constLocation&p)X=p.X;Y=p.Y;coutCopy_constructorcalled.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;voidmain()LocationA(1,2);LocationB(A);coutB:B.GetX(),B.GetY()endl;调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 /例例 用已有对象初始化新创建对象用已有对象初始化新创建对象 #includeclassLocationp

60、ublic:Location(intxx=0,intyy=0)X=xx;Y=yy;Location(constLocation&p)X=p.X;Y=p.Y;coutCopy_constructorcalled.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;voidmain()LocationA(1,2);LocationB(A);coutB:B.GetX(),B.GetY()endl;调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 / 调用复制构造函数调用复制构造函数/例例 函数的类类型实参

61、初始化形参时,要调用复制构造函数函数的类类型实参初始化形参时,要调用复制构造函数 #includeclassLocationpublic:Location(intxx=0,intyy=0)X=xx;Y=yy;coutConstructorObject.n;Location(constLocation&p)/复制构造函数复制构造函数X=p.X;Y=p.Y;coutCopy_constructorcalled.endl;Location()coutX,YObjectdestroyed.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;voi

62、df(Locationp)coutFuntion:p.GetX(),p.GetY()endl;voidmain()LocationA(1,2);f(A);调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 /例例 函数的类类型实参初始化形参时,要调用复制构造函数函数的类类型实参初始化形参时,要调用复制构造函数 #includeclassLocationpublic:Location(intxx=0,intyy=0)X=xx;Y=yy;coutConstructorObject.n;Location(constLocation&p)/复制构造函数复制构造函数

63、X=p.X;Y=p.Y;coutCopy_constructorcalled.endl;Location()coutX,YObjectdestroyed.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;voidf(Locationp)coutFuntion:p.GetX(),p.GetY()endl;voidmain()LocationA(1,2);f(A);调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 析构对象析构对象A/例例 函数返回类类型时,通过复制构造函数建立临时对象函数返回类类型时

64、,通过复制构造函数建立临时对象 #includeclassLocationpublic:Location(intxx=0,intyy=0)X=xx;Y=yy;coutObjectconstructed.endl;Location(constLocation&p)X=p.X;Y=p.Y;coutCopy_constructorcalled.endl;Location()coutX,YObjectdestroyed.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构

65、造函数的时机 Locationg()LocationA(1,2);returnA;voidmain()LocationB;B=g();Locationg()LocationA(1,2);returnA;voidmain()LocationB;B=g();/例例 函数返回类类型时,通过复制构造函数建立临时对象函数返回类类型时,通过复制构造函数建立临时对象 #includeclassLocationpublic:Location(intxx=0,intyy=0)X=xx;Y=yy;coutObjectconstructed.endl;Location(constLocation&p)X=p.X;Y

66、=p.Y;coutCopy_constructorcalled.endl;Location()coutX,YObjectdestroyed.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;LocationB;调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 构造对象构造对象BLocationg()LocationA(1,2);returnA;voidmain()LocationB;B=g();/例例 函数返回类类型时,通过复制构造函数建立临时对象函数返回类类型时,通过复制构造函数建立临时对象 #

67、includeclassLocationpublic:Location(intxx=0,intyy=0)X=xx;Y=yy;coutObjectconstructed.endl;Location(constLocation&p)X=p.X;Y=p.Y;coutCopy_constructorcalled.endl;Location()coutX,YObjectdestroyed.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;B=g();调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 Loca

68、tiong()LocationA(1,2);returnA;voidmain()LocationB;B=g();/例例 函数返回类类型时,通过复制构造函数建立临时对象函数返回类类型时,通过复制构造函数建立临时对象 #includeclassLocationpublic:Location(intxx=0,intyy=0)X=xx;Y=yy;coutObjectconstructed.endl;Location(constLocation&p)X=p.X;Y=p.Y;coutCopy_constructorcalled.endl;Location()coutX,YObjectdestroyed.e

69、ndl;intGetX()returnX;intGetY()returnY;private:intX,Y;LocationA(1,2);调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 Locationg()LocationA(1,2);returnA;voidmain()LocationB;B=g();/例例 函数返回类类型时,通过复制构造函数建立临时对象函数返回类类型时,通过复制构造函数建立临时对象 #includeclassLocationpublic:Location(intxx=0,intyy=0)X=xx;Y=yy;coutObjectcon

70、structed.endl;Location(constLocation&p)X=p.X;Y=p.Y;coutCopy_constructorcalled.endl;Location()coutX,YObjectdestroyed.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;LocationA(1,2);调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 构造局部对象构造局部对象ALocationg()LocationA(1,2);returnA;voidmain()LocationB;B=g

71、();/例例 函数返回类类型时,通过复制构造函数建立临时对象函数返回类类型时,通过复制构造函数建立临时对象 #includeclassLocationpublic:Location(intxx=0,intyy=0)X=xx;Y=yy;coutObjectconstructed.endl;Location(constLocation&p)X=p.X;Y=p.Y;coutCopy_constructorcalled.endl;Location()coutX,YObjectdestroyed.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;

72、returnA;调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 Locationg()LocationA(1,2);returnA;voidmain()LocationB;B=g();/例例 函数返回类类型时,通过复制构造函数建立临时对象函数返回类类型时,通过复制构造函数建立临时对象 #includeclassLocationpublic:Location(intxx=0,intyy=0)X=xx;Y=yy;coutObjectconstructed.endl;Location(constLocation&p)X=p.X;Y=p.Y;coutCopy_

73、constructorcalled.endl;Location()coutX,YObjectdestroyed.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;returnA;调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 把局部对象把局部对象A复制到匿名对象复制到匿名对象Locationg()LocationA(1,2);returnA;voidmain()LocationB;B=g();/例例 函数返回类类型时,通过复制构造函数建立临时对象函数返回类类型时,通过复制构造函数建立临时对象 #

74、includeclassLocationpublic:Location(intxx=0,intyy=0)X=xx;Y=yy;coutObjectconstructed.endl;Location(constLocation&p)X=p.X;Y=p.Y;coutCopy_constructorcalled.endl;Location()coutX,YObjectdestroyed.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;B=g();调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 执行默认

75、赋值重载运算执行默认赋值重载运算匿名对象数据赋给对象匿名对象数据赋给对象BLocationg()LocationA(1,2);returnA;voidmain()LocationB;B=g();/例例 函数返回类类型时,通过复制构造函数建立临时对象函数返回类类型时,通过复制构造函数建立临时对象 #includeclassLocationpublic:Location(intxx=0,intyy=0)X=xx;Y=yy;coutObjectconstructed.endl;Location(constLocation&p)X=p.X;Y=p.Y;coutCopy_constructorcalle

76、d.endl;Location()coutX,YObjectdestroyed.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 Locationg()LocationA(1,2);returnA;voidmain()LocationB;B=g();/例例 函数返回类类型时,通过复制构造函数建立临时对象函数返回类类型时,通过复制构造函数建立临时对象 #includeclassLocationpublic:Location(intxx=0,intyy

77、=0)X=xx;Y=yy;coutObjectconstructed.endl;Location(constLocation&p)X=p.X;Y=p.Y;coutCopy_constructorcalled.endl;Location()coutX,YObjectdestroyed.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 析构匿名对象析构匿名对象Locationg()LocationA(1,2);returnA;voidmain()Loc

78、ationB;B=g();/例例 函数返回类类型时,通过复制构造函数建立临时对象函数返回类类型时,通过复制构造函数建立临时对象 #includeclassLocationpublic:Location(intxx=0,intyy=0)X=xx;Y=yy;coutObjectconstructed.endl;Location(constLocation&p)X=p.X;Y=p.Y;coutCopy_constructorcalled.endl;Location()coutX,YObjectdestroyed.endl;intGetX()returnX;intGetY()returnY;priva

79、te:intX,Y;调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 析构局部对象析构局部对象ALocationg()LocationA(1,2);returnA;voidmain()LocationB;B=g();/例例 函数返回类类型时,通过复制构造函数建立临时对象函数返回类类型时,通过复制构造函数建立临时对象 #includeclassLocationpublic:Location(intxx=0,intyy=0)X=xx;Y=yy;coutObjectconstructed.endl;Location(constLocation&p)X=p.X;

80、Y=p.Y;coutCopy_constructorcalled.endl;Location()coutX,YObjectdestroyed.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 析构对象析构对象BLocationg()LocationA(1,2);returnA;voidmain()LocationB;B=g();/例例 函数返回类类型时,通过复制构造函数建立临时对象函数返回类类型时,通过复制构造函数建立临时对象 #includecl

81、assLocationpublic:Location(intxx=0,intyy=0)X=xx;Y=yy;coutObjectconstructed.endl;Location(constLocation&p)X=p.X;Y=p.Y;coutCopy_constructorcalled.endl;Location()coutX,YObjectdestroyed.endl;intGetX()returnX;intGetY()returnY;private:intX,Y;调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机调用复制构造函数的时机 默认复制构造函数可以完成对象的数据成员

82、值简单的复制对象的数据资源是由指针指示的堆时,默认复制构造函数仅作指针值复制浅复制和深复制浅复制和深复制浅复制和深复制浅复制和深复制 复制构造函数复制构造函数/例程序例程序#include#includeclassnamepublic:name(char*pn);name();protected:char*pname;intsize;name:name(char*pn)coutConstructingpnendl;pname=newcharstrlen(pn)+1;if(pname!=0)strcpy(pname,pn);size=strlen(pn);name:name(constname&

83、Obj)coutCopyingObj.pnameintoitsownblockn;pname=newcharstrlen(Obj.pname)+1;if(pname!=0)strcpy(pname,Obj.pname);size=Obj.size;name:name()coutDestructingpnameendl;pname0=0;deletepname;size=0;浅复制和深复制浅复制和深复制浅复制和深复制浅复制和深复制 voidmain()nameObj1(NoName);nameObj2=Obj1;/例程序例程序#include#includeclassnamepublic:nam

84、e(char*pn);name();protected:char*pname;intsize;name:name(char*pn)coutConstructingpnendl;pname=newcharstrlen(pn)+1;if(pname!=0)strcpy(pname,pn);size=strlen(pn);name:name(constname&Obj)coutCopyingObj.pnameintoitsownblockn;pname=newcharstrlen(Obj.pname)+1;if(pname!=0)strcpy(pname,Obj.pname);size=Obj.si

85、ze;name:name()coutDestructingpnameendl;pname0=0;deletepname;size=0;浅复制和深复制浅复制和深复制浅复制和深复制浅复制和深复制 定义复制构造函数定义复制构造函数voidmain()nameObj1(NoName);nameObj2=Obj1;/例程序例程序#include#includeclassnamepublic:name(char*pn);name();protected:char*pname;intsize;name:name(char*pn)coutConstructingpnendl;pname=newcharstrl

86、en(pn)+1;if(pname!=0)strcpy(pname,pn);size=strlen(pn);name:name(name&Obj)coutCopyingObj.pnameintoitsownblockn;pname=newcharstrlen(Obj.pname)+1;if(pname!=0)strcpy(pname,Obj.pname);size=Obj.size;name:name()coutDestructingpnameendl;pname0=0;deletepname;size=0;浅复制和深复制浅复制和深复制浅复制和深复制浅复制和深复制 voidmain()name

87、Obj1(NoName);nameObj2=Obj1;NoName06Obj1.pnameObj1.size/例程序例程序#include#includeclassnamepublic:name(char*pn);name();protected:char*pname;intsize;name:name(char*pn)coutConstructingpnendl;pname=newcharstrlen(pn)+1;if(pname!=0)strcpy(pname,pn);size=strlen(pn);name:name(name&Obj)coutCopyingObj.pnameintoit

88、sownblockn;pname=newcharstrlen(Obj.pname)+1;if(pname!=0)strcpy(pname,Obj.pname);size=Obj.size;name:name()coutDestructingpnameendl;pname0=0;deletepname;size=0;浅复制和深复制浅复制和深复制浅复制和深复制浅复制和深复制 NoName06Obj1.pnameObj1.sizevoidmain()nameObj1(NoName);nameObj2=Obj1;6Obj2.pnameObj2.sizeNoName0/例程序例程序#include#in

89、cludeclassnamepublic:name(char*pn);name();protected:char*pname;intsize;name:name(char*pn)coutConstructingpnendl;pname=newcharstrlen(pn)+1;if(pname!=0)strcpy(pname,pn);size=strlen(pn);name:name(constname&Obj)coutCopyingObj.pnameintoitsownblockn;pname=newcharstrlen(Obj.pname)+1;if(pname!=0)strcpy(pnam

90、e,Obj.pname);size=Obj.size;name:name()coutDestructingpnameendl;pname0=0;deletepname;size=0;浅复制和深复制浅复制和深复制浅复制和深复制浅复制和深复制 NoName06Obj1.pnameObj1.sizevoidmain()nameObj1(NoName);nameObj2=Obj1;6Obj2.pnameObj2.sizeNoName0/例程序例程序#include#includeclassnamepublic:name(char*pn);name();protected:char*pname;ints

91、ize;name:name(char*pn)coutConstructingpnendl;pname=newcharstrlen(pn)+1;if(pname!=0)strcpy(pname,pn);size=strlen(pn);name:name(constname&Obj)coutCopyingObj.pnameintoitsownblockn;pname=newcharstrlen(Obj.pname)+1;if(pname!=0)strcpy(pname,Obj.pname);size=Obj.size;name:name()coutDestructingpnameendl;pnam

92、e0=0;deletepname;size=0;浅复制和深复制浅复制和深复制浅复制和深复制浅复制和深复制 NoName06Obj1.pnameObj1.sizevoidmain()nameObj1(NoName);nameObj2=Obj1;6Obj2.pnameObj2.sizeNoName0/例程序例程序#include#includeclassnamepublic:name(char*pn);name();protected:char*pname;intsize;name:name(char*pn)coutConstructingpnendl;pname=newcharstrlen(pn

93、)+1;if(pname!=0)strcpy(pname,pn);size=strlen(pn);name:name(constname&Obj)coutCopyingObj.pnameintoitsownblockn;pname=newcharstrlen(Obj.pname)+1;if(pname!=0)strcpy(pname,Obj.pname);size=Obj.size;name:name()coutDestructingpnameendl;pname0=0;deletepname;size=0;浅复制和深复制浅复制和深复制浅复制和深复制浅复制和深复制 NoName06Obj1.p

94、nameObj1.sizevoidmain()nameObj1(NoName);nameObj2=Obj1;6Obj2.pnameObj2.sizeNoName0默认的拷贝构造函数默认的拷贝构造函数如果程序员没有为类声明拷贝初始化构造函数,则编译器自己生成一个默认的拷贝构造函数。这个构造函数执行的功能是:用作为初始值的对象的每个数据成员的值,初始化将要建立的对象的对应数据成员。9.4.5 析构函数析构函数n析构函数是用于取消对象的成员函数n当一个对象作用域结束时,系统自动调用析构函数n析构函数的作用是进行清除对象,释放内存等n没有用户定义析构函数时,系统提供缺省版本的析构函数n 析构函数名为:

95、 类名n 析构函数没有参数,也没有返回类型(1)如果一个对象被定义在一个函数体内,则当这个函数结束时,该对象的析构函数被自动调用。(2)若一个对象是使用new运算符动态创建的,在使用delete运算符释放它时,delete将会自动调用析构函数。如同默认构造函数一样,如果一个类没有定义析构函数,编译器会自动生成一个默认析构函数,其格式如下::()默认析构函数是一个空函数。例:例:classAApublic:AA()AA();voidtest()intx,y;AAt1,t2;return;构造函数和析构函数构造函数和析构函数构造函数和析构函数构造函数和析构函数 例:例:classAApublic:

96、AA()AA();voidtest()intx,y;AAt1,t2;return;构造函数和析构函数构造函数和析构函数构造函数和析构函数构造函数和析构函数 构造函数构造函数例:例:classAApublic:AA()AA();voidtest()intx,y;AAt1,t2;return;构造函数和析构函数构造函数和析构函数构造函数和析构函数构造函数和析构函数 析构函数析构函数例:例:classAApublic:AA()AA();voidtest()intx,y;AAt1,t2;return;构造函数和析构函数构造函数和析构函数构造函数和析构函数构造函数和析构函数 / 声明变量时开辟两个整型存

97、储空间声明变量时开辟两个整型存储空间例:例:classAApublic:AA()AA();voidtest()intx,y;AAt1,t2;return;构造函数和析构函数构造函数和析构函数构造函数和析构函数构造函数和析构函数 / 两次调用构造函数,创建对象两次调用构造函数,创建对象例:例:classAApublic:AA()AA();voidtest()intx,y;AAt1,t2;return;构造函数和析构函数构造函数和析构函数构造函数和析构函数构造函数和析构函数 / 两次调用构造函数,创建对象两次调用构造函数,创建对象例:例:classAApublic:AA()AA();voidtes

98、t()intx,y;AAt1,t2;return;构造函数和析构函数构造函数和析构函数构造函数和析构函数构造函数和析构函数 /两次调用析构函数,撤消对象两次调用析构函数,撤消对象例:例:classAApublic:AA()AA();voidtest()intx,y;AAt1,t2;return;构造函数和析构函数构造函数和析构函数构造函数和析构函数构造函数和析构函数 /两次调用析构函数,撤消对象两次调用析构函数,撤消对象例:例:classAApublic:AA()AA();voidtest()intx,y;AAt1,t2;return;构造函数和析构函数构造函数和析构函数构造函数和析构函数构造

99、函数和析构函数 / 变量变量 x, y 生存期结束生存期结束/两次调用析构函数,撤消对象两次调用析构函数,撤消对象简单构造函数和析构函数简单构造函数和析构函数 构造函数原型类名:类名(参数表);析构函数原型类名 : 类名();#includeclassDatepublic:Date();Date();voidSetDate(inty,intm,intd);intIsLeapYear();voidPrintDate();private:intyear,month,day;Date:Date()coutDateobjectinitialized.n;/ 无参构造函数无参构造函数Date:Date(

100、)coutDateobjectdestroyed.n;/ 析构函数析构函数voidDate:SetDate(inty,intm,intd)year=y;month=m;day=d;intDate:IsLeapYear()return(year%4=0&year%100!=0)|(year%400=0);voidDate:PrintDate()coutyear/month/dayendl;voidmain()Dated;d.SetDate(2001,10,1);d.PrintDate();#includeclassDatepublic:Date();Date();voidSetDate(inty

101、,intm,intd);intIsLeapYear();voidPrintDate();private:intyear,month,day;Date:Date()coutDateobjectinitialized.n;/ 无参构造函数无参构造函数Date:Date()coutDateobjectdestroyed.n;/ 析构函数析构函数voidDate:SetDate(inty,intm,intd)year=y;month=m;day=d;intDate:IsLeapYear()return(year%4=0&year%100!=0)|(year%400=0);voidDate:PrintD

102、ate()coutyear/month/dayendl;voidmain()Dated;d.SetDate(2001,10,1);d.PrintDate();Date();Date:Date()coutDateobjectinitialized.n;/ 无参无参构造函数构造函数Dated;创建对象时创建对象时调用构造函数调用构造函数#includeclassDatepublic:Date();Date();voidSetDate(inty,intm,intd);intIsLeapYear();voidPrintDate();private:intyear,month,day;Date:Date

103、()coutDateobjectinitialized.n;/ 无参构造函数无参构造函数Date:Date()coutDateobjectdestroyed.n;/ 析构函数析构函数voidDate:SetDate(inty,intm,intd)year=y;month=m;day=d;intDate:IsLeapYear()return(year%4=0&year%100!=0)|(year%400=0);voidDate:PrintDate()coutyear/month/dayendl;voidmain()Dated;d.SetDate(2001,10,1);d.PrintDate();

104、Date();Date:Date()coutDateobjectdestroyed.n;/ 析构函数析构函数作用域结束时作用域结束时调用析构函数调用析构函数#includeclassDatepublic:Date();Date();voidSetDate(inty,intm,intd);intIsLeapYear();voidPrintDate();private:intyear,month,day;Date:Date()coutDateobjectinitialized.n;/ 无参构造函数无参构造函数Date:Date()coutDateobjectdestroyed.n;/ 析构函数析构

105、函数voidDate:SetDate(inty,intm,intd)year=y;month=m;day=d;intDate:IsLeapYear()return(year%4=0&year%100!=0)|(year%400=0);voidDate:PrintDate()coutyear/month/dayendl;voidmain()Dated;d.SetDate(2001,10,1);d.PrintDate();#includeclassDatepublic:Date();Date();voidSetDate(inty,intm,intd);intIsLeapYear();voidPri

106、ntDate();private:intyear,month,day;Date:Date()coutDateobjectinitialized.n;/ 无参构造函数无参构造函数Date:Date()coutDateobjectdestroyed.n;/ 析构函数析构函数voidDate:SetDate(inty,intm,intd)year=y;month=m;day=d;intDate:IsLeapYear()return(year%4=0&year%100!=0)|(year%400=0);voidDate:PrintDate()coutyear/month/dayendl;voidmai

107、n()Dated;d.SetDate(2001,10,1);d.PrintDate();#includeclassDatepublic:Date();Date();voidSetDate(inty,intm,intd);intIsLeapYear();voidPrintDate();private:intyear,month,day;Date:Date()coutDateobjectinitialized.n;/ 无参构造函数无参构造函数Date:Date()coutDateobjectdestroyed.n;/ 析构函数析构函数voidDate:SetDate(inty,intm,intd)

108、year=y;month=m;day=d;intDate:IsLeapYear()return(year%4=0&year%100!=0)|(year%400=0);voidDate:PrintDate()coutyear/month/dayendl;voidmain()Dated;d.SetDate(2001,10,1);d.PrintDate();Date*pd=new(Date);Date();Date:Date()coutDateobjectinitialized.n;/ 无参无参构造函数构造函数创建动态对象时创建动态对象时调用构造函数调用构造函数#includeclassDatepu

109、blic:Date();Date();voidSetDate(inty,intm,intd);intIsLeapYear();voidPrintDate();private:intyear,month,day;Date:Date()coutDateobjectinitialized.n;/ 无参构造函数无参构造函数Date:Date()coutDateobjectdestroyed.n;/ 析构函数析构函数voidDate:SetDate(inty,intm,intd)year=y;month=m;day=d;intDate:IsLeapYear()return(year%4=0&year%1

110、00!=0)|(year%400=0);voidDate:PrintDate()coutyear/month/dayendl;voidmain()Dated;d.SetDate(2001,10,1);d.PrintDate();deletepd;Date();Date:Date()coutDateobjectdestroyed.n;/ 析构函数析构函数释放动态对象时释放动态对象时调用析构函数调用析构函数调用构造函数和析构函数的顺序调用构造函数和析构函数的顺序对象对象1的的构造函数构造函数对象对象2的的构造函数构造函数对象对象3的的构造函数构造函数对象对象3的的析构函数析构函数对象对象2的的析构

111、函数析构函数对象对象1的的析构函数析构函数#include string#include iostreamusing namespace std;class studentpublic:student(int n,string nam,char s) num=n; name=nam; sex=s; cout Constructor called.endl;student() coutDestructor called.numendl;void display()coutnum:numendl;coutname:nameendl;coutsex:sexendlendl;private: int

112、num; string name; char sex;int main() student stud1(10010,Wang_li,f); stud1. display(); student stud2(10011,Zhang_fan,m); stud2. display(); return 0;(1)分析 书目类的主要属性有:书号、书名、数量等; 例 下面的程序用来建立书目表,并且程序运行结束时,自动撤消之(释放表空间)。 书目类的主要操作有:建立书目表,由构造函数自动完成;输入书目信息,由input成员函数完成;显示书目表,由display成员函数完成。 (2)定义书目类,并保存到Tboo

113、k.h文件中 struct Bookitem int Bookcode; char Bookname31; int amount; 构造函数和析构函数举例构造函数和析构函数举例class Book protected: Bookitem *BI; public: Book(int n) /Book类的构造函数 BI=new Bookitemn;/分配结构数组空间 ; Book() /Book类的析构函数 delete BI; /释放结构数组空间 ; void display(int n); void input(int n); /其它成员函数; #include#includevoidBook

114、:display(intn)inti;for(i=0;in;i+)cout书号BIi.Bookcode;cout书名BIi.Booknameendl;cout数量BIi.Amountendl;voidBook:input(intn)inti;for(i=0;in;i+)coutBIi.Bookcode; cout BIi.Bookname; cout BIi.Amount; display(n);void main() Book b(100); int n; cout n; b.input(n); /声明书目对象,该对象包含声明书目对象,该对象包含100100份书目明细份书目明细/输入书目明细

115、输入书目明细类的应用举例类的应用举例一圆形游泳池如图所示,现在需在其周围建一圆形过道,并在其四周围上栅栏。栅栏价格为35元/米,过道造价为20元/平方米。过道宽度为3米,游泳池半径由键盘输入。要求编程计算并输出过道和栅栏的造价。游泳池过道#include using namespace std;const float PI = 3.14159;const float FencePrice = 35;const float ConcretePrice = 20;/声明类Circle 及其数据和方法class Circle private: float radius; public: Circle

116、(float r); /构造函数 float Circumference() const; /圆周长 float Area() const; /圆面积;153/ 类的实现/ 构造函数初始化数据成员radius Circle:Circle(float r)radius=r/ 计算圆的周长float Circle:Circumference() const return 2 * PI * radius; / 计算圆的面积 float Circle:Area() const return PI * radius * radius;154void main () float radius; float

117、 FenceCost, ConcreteCost; / 提示用户输入半径 coutradius; / 声明 Circle 对象 Circle Pool(radius); Circle PoolRim(radius + 3); 155 /计算栅栏造价并输出 FenceCost=PoolRim.Circumference()*FencePrice; coutFencing Cost is ¥FenceCostendl; /计算过道造价并输出 ConcreteCost=(PoolRim.Area()- Pool.Area()*ConcretePrice; coutConcrete Cost is ¥

118、ConcreteCostendl;运行结果Enter the radius of the pool: 10Fencing Cost is ¥2858.85Concrete Cost is ¥4335.391569.5 类的初始化类的初始化C+允许以下3 种数据初始化方法:(1)初始值表:适用于结构和数组的初始化。例如: struct conf char *month; int day; int year; cpp =“Nov.” , 12 , 1998 , “Oct.” , 8, 1999, “April” , 6 , 2000 (2)赋值表达式:适用于简单变量或指针类型的初始化。例如: in

119、t i = 1 ; char *p = “No. 1” ; (3)表达式表:与方法(2)语义相同,风格不一样。例如: int i (1) ; char *p ( “No. 1” ) ; 构造函数的初始化主要采用表达式表的方法。2. C+中,类的初始化分为两种情况:中,类的初始化分为两种情况:(1)对仅有公有段成员,而没有构造函数或基类的类对象,用初始值表来表示。典型例子是结构。(2)带有构造函数的类的初始化。 例如:classXpublic:X();X(inti);private:inti;main()Xone;/调用无参构造函数X:X()Xtwo(1);/调用构造函数X:X(int),/表达

120、式表Xthree=1;/调用构造函数X:X(int),/赋值表达式初始化时,构造函数可用两种方式把值赋给成员:初始化时,构造函数可用两种方式把值赋给成员:(1)接受该值作为参量,并在构造函数体内赋给其成员。例如:class X int a, b ; / 默认为 private 成员 public: X( int i , int j ) a = i ; b = j ; (2)使用函数体前的初值表(冒号语法)。例如:代替函数体内对一般成员赋值示例。class X int a, b ; public: X( int i , int j ) : a ( i ) , b ( j ) ; n使用默认参数的

121、构造函数#include“iostream.h”usingnamespacestd;ClassBoxpublic:Box(inth=10,intw=10,intlen=10);intvolume();private:intheight;intwidth;intlength;Box:Box(inth,intw,intlen)height=h;width=w;length=len;intBox:volume()return(height*width*length);intmain()Boxbox1;cout“Thevolumeoftheboxis”box1.volume()endl;Boxbox2

122、(15);cout“Thevolumeoftheboxis”box2.volume()endl;Boxbox3(15,30);cout“Thevolumeoftheboxis”box3.volume()endl;Boxbox4(15,30,20);cout“Thevolumeoftheboxis”box4.volume()endl;关键字static可以用于说明一个类的成员静态成员提供了一个同类对象的共享机制把一个类的成员说明为static时,这个类无论有多少个对象被创建,这些对象共享这个static成员静态成员局部于类,它不是对象成员9.6 静态成员和静态成员函数b.chc.chd.ch示例

123、:示例:示例:示例:a.chstaticints;staticints;被各个对象共有被各个对象共有/例例 静态数据成员的说明和初始化静态数据成员的说明和初始化#includeclasscounterstaticintnum;public:voidsetnum(inti)num=i;voidshownum()coutnumt;intcounter:num=0;voidmain()countera,b;a.shownum();b.shownum();a.setnum(10);a.shownum();b.shownum();/例例 静态数据成员的说明和初始化静态数据成员的说明和初始化 #inclu

124、declasscounterstaticintnum;public:voidsetnum(inti)num=i;voidshownum()coutnumt;intcounter:num=0;voidmain()countera,b;a.shownum();b.shownum();a.setnum(10);a.shownum();b.shownum();访问同一个访问同一个静态数据成员静态数据成员/ 例例 使用公有静态数据成员使用公有静态数据成员 #includeclasscounterpublic:counter(inta)mem=a;intmem;/公有数据成员公有数据成员staticint

125、Smem;/公有静态数据成员公有静态数据成员;intcounter:Smem=1;/初始值为初始值为1voidmain()counterc(5);inti;for(i=0;i5;i+)counter:Smem+=i;coutcounter:Smemt;coutendl;coutc.Smem=c.Smemendl;coutc.mem=c.memendl;/ 例例 使用公有静态数据成员使用公有静态数据成员 #includeclasscounterpublic:counter(inta)mem=a;intmem;/公有数据成员公有数据成员staticintSmem;/公有静态数据成员公有静态数据成员

126、;intcounter:Smem=1;/初始值为初始值为1voidmain()counterc(5);inti;for(i=0;i5;i+)counter:Smem+=i;coutcounter:Smemt;coutendl;coutc.Smem=c.Smemendl;coutc.mem=c.memDatMem=i;/ 正确正确voidX:StaFun(inti,X*ptr)类的静态成员函数类的静态成员函数通过参数访问私有数据成员通过参数访问私有数据成员静态成员函数例如例如classXintDatMem;public:staticvoidStaFun(inti,X*ptr);ptr-DatMe

127、m=i;/ 正确正确voidX:StaFun(inti,X*ptr)voidg()Xobj;X:StaFun(1,&obj);/ 正确正确obj.StaFun(1,&obj);/ 正确正确都表示都表示静态成员函数的地址静态成员函数的地址静态成员函数某商店经销一种货物。货物购进和卖出时以箱为单位,各箱的重量不一样,因此,商店需要记录目前库存的总重量。现在用C+模拟商店货物购进和卖出的情况。例例静态成员函数#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeigh

128、t()returnweight;staticintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsale

129、d.n;#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL

130、;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttot

131、al_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;析造函数析造函数售出货物售出货物#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weig

132、ht-=weight;intWeight()returnweight;staticintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutne

133、xt;deleteq;coutsaled.n;front981703150rearfr200w200p349total_weight#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidp

134、urchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;front981703150rearfr200w200p调用构造函数调用构造函数累加货物重量累加货物重量Goods:Goods(intw)weight=w;total_weight+=w;349total_weight#includeclassGoodspublic

135、:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=

136、p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;front981703150rearfr200w200p调用构造函数调用构造函数累加货物重量累加货物重量Goods:Goods(intw)weight=w;total_weight+=w;549549total_weight#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweigh

137、t;staticintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;front98170

138、3150rearfr200w200p549549total_weight#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw

139、)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;front981703150rearfr200w200p549549total_weight#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;stat

140、icintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;front981703150re

141、arfr200w200p549549total_weight#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods

142、*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;front981703150rearfr200w200549549total_weight#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTo

143、talWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;front981703150f200w200r

144、earr549549total_weight#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGo

145、ods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;frfront981703150rear200549total_weight#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()retu

146、rntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;frfront981703150rear200549total_weight

147、#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(

148、f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;frfront981703150rear200549total_weightq#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()returntotal_weight;Goods*

149、next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;frfront981703150rear200549total_weightq#includeclassGoodspu

150、blic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-n

151、ext=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;frfront981703150rear200549total_weightq#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()returntotal_weight;Goods*next;private:intweig

152、ht;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;frfront981703150rear200q549total_weight#includeclassGoodspublic:Goods(intw)weig

153、ht=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voids

154、ale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;frfront981703150rear200q调用析造函数调用析造函数减去货物重量减去货物重量549total_weightGoods:Goods()total_weight-=weight;#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()returnt

155、otal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;frfront981703150rear200q调用析造函数调用析造函数减去货物重

156、量减去货物重量499499total_weightGoods:Goods()total_weight-=weight;#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;Goods()total_weight-=weight;intWeight()returnweight;staticintTotalWeight()returntotal_weight;Goods*next;private:intweight;staticinttotal_weight;intGoods:total_weight=0;voidpurchase

157、(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;if(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;frfront9817031rear200499499total_weightvoidmain()Goods*front=NULL,*rear=NULL;intw;intchoice;docoutPleasechoice:n;coutchoice;switch(choice)/

158、操作选择操作选择case1:/ 键入键入1,购进,购进1箱货物箱货物coutw;purchase(front,rear,w);/ 从表尾插入从表尾插入1个结点个结点break;case2:/ 键入键入2,售出,售出1箱货物箱货物sale(front,rear);break;/ 从表头删除从表头删除1个结点个结点case0:break;/ 键入键入0,结束,结束coutNowtotalweightis:Goods:TotalWeight()”运算符访问对象成员 访问对象成员访问对象成员 具有类指针参数具有类指针参数的函数的函数公有成员是提供给外部的接口类外用“.”和“-”运算符访问对象成员 访问

159、对象成员访问对象成员 向函数向函数传递对象地址传递对象地址类对象的数组 constintMAX_SIZE=50;/declarearrayofclassobjectsTimeTypetrainScheduleMAX_SIZE;Thedefaultconstructor,ifthereis,isinvokedforeachelementofthearray.TimeType 的说明classTimeType/ timetype.hpublic:/ 7 function membersvoid Set(inthours,intminutes, intseconds);void Increment(

160、);void Write()const;BooleanEqual(TimeTypeotherTime)const;BooleanLessThan(TimeTypeotherTime)const;TimeType(intinitHrs, intinitMins, intinitSecs);/ constructorTimeType();/ default constructorprivate:/ 3 data membersinthrs;intmins;intsecs;9.9 堆9.9.1 堆对象1. C+程序的内存布局C+程序的内存格局通常分为四个区:(1)全局数据区(data area) 存

161、放全局变量、静态数据、常量。(2)代码区(code area) 存放类成员函数、其他函数代码。 (3)栈区(stack area) 存放局部变量、函数参数、返回数据、返回地址。(4)堆区 (heap area) 。 自由存储区。 2. 堆对象堆对象是在程序运行时根据需要随时可以被创建或删除的对象,当创建堆对象时,堆中的一个存储单元从未分配状态变为已分配状态,可供其他动态当删除堆对象时,存储单元从分配状态又变为未分配状态数据使用。 9.9.2 new 和 delete与对基本数据类型操作一样,new 和 delete算符可以用于创建和删除堆对象。语法: new T (初始值 ) 创建一个T类型对

162、象,返回值为对象首地址new T E 创建一个T类型对象数组,返回值为数组首地址delete 指针变量删除一个指针变量所指的对象delete 指针变量删除一个指针变量所指的对象数组其中 T 是类型,E 是算术表达式公有成员是提供给外部的接口类外用“.”和“-”运算符访问对象成员 访问对象成员访问对象成员 建立建立动态对象动态对象9.10 this指针nthis指针只能在类的成员函数中使用nthis指针的类型就是成员函数所属的类的类型。当调用成员函数时,它被初始化为被调用函数所在的类实例的地址。n静态成员函数没有this指针this指针1. 1. 什么叫什么叫thisthis指针指针 this指

163、针是c+自动为每个类的成员函数定义的特殊指针,该指针作为隐含参数自动传递给成员函数,并指向调用成员函数的对象。 1 1) this指针的引入例如:Date d1,d2;d1.display(Date *const this);d2.display(Date *const this);d1对象d2对象void Date:display() cout month;/等价于cout month; 2) this指针的语法 2. this指针的特性 (1) this是每个成员函数的一个隐含参数,通过该参数,成员函数可以获知当前对象的地址,从而可以操纵对象所拥有的数据成员。显式使用this指针隐式使用t

164、his指针例 下面的程序显式地使用this指针标识调用成员函数的对象。 #includeclassApublic:A()a=b=0;A(inti,intj)a=i,b=j;voidCopy(A&ra);voidPrint()couta=a,b=bendl;private:inta,b;voidA:Copy(A&ra)if(this=&ra)return;/*若使用“a1.Copy(a1);”语句,即源对象和目的对象相同,不必复制,直接返回*/*this=ra;/*若A类对象a1调用本函数,则*this就是a1,即把形参引用ra(就是a2)位模式复制给调用本函数的对象(就是a1)*/voidma

165、in()Aa1,a2(3,4);coutBeforeCopying:n;a1.Print();a2.Print();a1.Copy(a2);/*(1)相当于执行了this=&a1;(2)相当于执行了A&ra=a2;(3)实现了a2复制到a1*/coutAfterCopying:n;a1.Print();a2.Print();输出:输出:BeforeCopying:a=0,b=0A=3,b=4AfterCopying:a=3,b=3A=3,b=4 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;

166、voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.printXY();obj3.setXY(30,35);obj3.printXY(); this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10

167、,15);obj1.printXY();obj2.setXY(20,25);obj2.printXY();obj3.setXY(30,35);obj3.printXY();obj1.xobj1.yobj2.xobj2.yobj3.xobj3.y this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20

168、,25);obj2.printXY();obj3.setXY(30,35);obj3.printXY();obj1.xobj1.yobj2.xobj2.yobj3.xobj3.y this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.printXY();obj3.setXY(30

169、,35);obj3.printXY();obj1.xobj1.yobj2.xobj2.yobj3.xobj3.y向哪个对象向哪个对象的数据成员赋值?的数据成员赋值? this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yx=a;this-y=b;obj1.setXY(10,15, &obj1 );成员函数隐含定义成员函数隐含定义this指针指针接受调用对象的地址接受调用对象的地址 this this指针指针 #includeclassSimpleintx,y;

170、public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yx=a;this-y=b; this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yx=a;this-y=b; this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,o

171、bj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.printXY();obj3.setXY(30,35);obj3.printXY();obj1.xobj1.yobj2.xobj2.yobj3.xobj3.y通过调用函数的对象通过调用函数的对象this指针获取对象地址指针获取对象地址 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleo

172、bj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.printXY();obj3.setXY(30,35);obj3.printXY();1015obj1.xobj1.yobj2.xobj2.yobj3.xobj3.y this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,1

173、5);obj1.printXY();obj2.setXY(20,25);obj2.printXY();obj3.setXY(30,35);obj3.printXY();1015obj1.xobj1.yobj2.xobj2.yobj3.xobj3.y this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(

174、20,25);obj2.printXY();obj3.setXY(30,35);obj3.printXY();1015obj1.xobj1.yobj2.xobj2.yobj3.xobj3.y在在obj1上操作上操作10,1520,2530,35 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20

175、,25);obj2.printXY();obj3.setXY(30,35);obj3.printXY();1015obj1.xobj1.yobj2.xobj2.yobj3.xobj3.y10,1520,2530,35 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.prin

176、tXY();obj3.setXY(30,35);obj3.printXY();1015obj1.xobj1.yobj2.xobj2.yobj3.xobj3.y10,1520,2530,35在在obj2上操作上操作 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.printX

177、Y();obj3.setXY(30,35);obj3.printXY();1015obj1.xobj1.y2025obj2.xobj2.yobj3.xobj3.y10,1520,2530,35在在obj2上操作上操作 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.prin

178、tXY();obj3.setXY(30,35);obj3.printXY();1015obj1.xobj1.y2025obj2.xobj2.yobj3.xobj3.y10,1520,2530,35 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.printXY();obj3

179、.setXY(30,35);obj3.printXY();1015obj1.xobj1.y2025obj2.xobj2.yobj3.xobj3.y10,1520,2530,35在在obj2上操作上操作 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.printXY();ob

180、j3.setXY(30,35);obj3.printXY();1015obj1.xobj1.y2025obj2.xobj2.yobj3.xobj3.y10,1520,2530,35在在obj2上操作上操作 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.printXY();

181、obj3.setXY(30,35);obj3.printXY();1015obj1.xobj1.y2025obj2.xobj2.yobj3.xobj3.y10,1520,2530,35 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.printXY();obj3.setXY

182、(30,35);obj3.printXY();1015obj1.xobj1.y2025obj2.xobj2.yobj3.xobj3.y10,1520,2530,35 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.printXY();obj3.setXY(30,35);ob

183、j3.printXY();1015obj1.xobj1.y2025obj2.xobj2.y3035obj3.xobj3.y10,1520,2530,35 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.printXY();obj3.setXY(30,35);obj3.pri

184、ntXY();1015obj1.xobj1.y2025obj2.xobj2.y3035obj3.xobj3.y10,1520,2530,35 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.printXY();obj3.setXY(30,35);obj3.printXY()

185、;1015obj1.xobj1.y2025obj2.xobj2.y3035obj3.xobj3.y10,1520,2530,35 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yendl;voidmain()Simpleobj1,obj2,obj3;obj1.setXY(10,15);obj1.printXY();obj2.setXY(20,25);obj2.printXY();obj3.setXY(30,35);obj3.printXY();1015o

186、bj1.xobj1.y2025obj2.xobj2.y3035obj3.xobj3.y10,1520,2530,35 this this指针指针 #includeclassSimpleintx,y;public:voidsetXY(inta,intb)x=a;y=b;voidprintXY()coutx,yi=x;voidA:MemberFun(intx)i=x;9.11.1 9.11.1 友员函数友员函数classAprivate:inti;friendvoidFriendFun(A*,int);public:voidMemberFun(int);voidFriendFun(A*ptr,in

187、tx)ptr-i=x;voidA:MemberFun(intx)i=x;9.11.1 9.11.1 友员函数友员函数说明语句位置说明语句位置与访问描述无关与访问描述无关classAprivate:int i ;friendvoidFriendFun(A*,int);public:voidMemberFun(int);voidFriendFun(A * ptr,intx)ptr - i=x;voidA:MemberFun(intx)i=x;9.12.1 9.12.1 友员函数友员函数友员函数通过对象参数友员函数通过对象参数访问私有数据成员访问私有数据成员9.12.1 9.12.1 友员函数友员函

188、数成员函数通过成员函数通过this指针指针在对象上操作在对象上操作classAprivate:int i ;friendvoidFriendFun(A*,int);public:voidMemberFun(int);voidFriendFun(A*ptr,intx)ptr-i=x;voidA:MemberFun(intx)i = x;9.12.1 9.12.1 友员函数友员函数classAprivate:int i ;friendvoidFriendFun(A*,int);public:voidMemberFun(int);voidFriendFun(voidFriendFun(A*ptrA*

189、ptr,intx),intx) ptr - iptr - i= x ; ;= x ; ; voidA:MemberFun(intx)i=x;#include#includeclassPointpublic:Point(doublexi,doubleyi)X=xi;Y=yi;doubleGetX()returnX;doubleGetY()returnY;frienddoubleDistance(Point&a,Point&b);private:doubleX,Y;doubleDistance(Point&a,Point&b)doubledx=a.X-b.X;doubledy=a.Y-b.Y;re

190、turnsqrt(dx*dx+dy*dy);voidmain()Pointp1(3.0,5.0),p2(4.0,6.0);doubled=Distance(p1,p2);coutThisdistanceisdendl;例例 用友员函数计算两点之间的距离用友员函数计算两点之间的距离 #include#includeclassPointpublic:Point(doublexi,doubleyi)X=xi;Y=yi;doubleGetX()returnX;doubleGetY()returnY;frienddoubleDistance(Point&a,Point&b);private:double

191、X,Y;doubleDistance(Point&a,Point&b)doubledx=a.X-b.X;doubledy=a.Y-b.Y;returnsqrt(dx*dx+dy*dy);voidmain()Pointp1(3.0,5.0),p2(4.0,6.0);doubled=Distance(p1,p2);coutThisdistanceisdendl;例例 用友员函数计算两点之间的距离用友员函数计算两点之间的距离 TRUE or FALSE ? C+允许一个结构类型作为另一个结构的成员类型. A)TrueB)False TRUE or FALSE ?vTRUETRUE or FALSE

192、? C+ 不允许在结构类型上进行整体操作. A)TrueB)FalseTRUE or FALSE ?vFALSETRUE or FALSE ? 在C+中, 一个结构类型作为参数,既可以传递为数值参数,也可以传递为引用(地址)传递.A)TrueB)FalseTRUE or FALSE ?vTRUETRUE or FALSE ? 一个ADT的用户使用ADT的说明,不需要了解其实现A)TrueB)FalseTRUE or FALSE ?vTRUETRUE or FALSE ? C+的客户端能够直接访问公有的和私有的成员(Clients of a C+ class can access the pub

193、lic and private members directly. )A)TrueB)FalseTRUE or FALSE ?vFALSETRUE or FALSE ? 在C+中, 两种不同的类,-叫做 MyClass 和YourClass不能都有称为Subtract 的成员函数. A)TrueB)FalseTRUE or FALSE ?vFALSETRUE or FALSE ? C+ 类的成员函数的名称不能够同名.A)TrueB)FalseTRUE or FALSE ?vFALSETRUE or FALSE ? 一个C+ 的构造函数不能够返回一个函数值. A)TrueB)FalseTRUE

194、or FALSE ?vTRUE选择 在C+中, 下面哪一个不用结构的整体操作?A)赋值值B)I/O B)I/O C)函数的值传递D)函数的引用传递 E)返回作为函数的返回值值选择vB选择 假设声明为:假设声明为: struct RecType1 int length; float width; ; struct RecType2 int length; float width; ; RecType1 myRec; RecType2 yourRec;下面哪一条赋值语句是有效的?下面哪一条赋值语句是有效的?A)myRec.length = yourRec.length; B)myRec = you

195、rRec; C)myRec.length = yourRec; D)a and b above 选择vA选择 考虑类的声明考虑类的声明 class SomeClass public: void Func(); private: int m; int n; ;客户端代码客户端代码 SomeClass alpha; SomeClass beta; .考虑上述两段代码,哪一个标识符是类的成员的名字?考虑上述两段代码,哪一个标识符是类的成员的名字?A)m and n B)alpha and beta C)SomeClass, m, and n D)alpha, beta, m, and n E)Func, m, and n 选择vE选择 假设类的声明为 class X public: void F( int ); private: int n; ;下面哪一条客户代码会产生实时的编译错误? X alpha; / Line 1 alpha.F(3); / Line 2 alpha.n = 42; / Line 3 A)line 1 B)line 2 C)line 3 D)lines 1 and 2 E)lines 2 and 3 选择vC

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 研究生课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号