面向对象程序设计语言C++-精品课模板cs_第1页
面向对象程序设计语言C++-精品课模板cs_第2页
面向对象程序设计语言C++-精品课模板cs_第3页
面向对象程序设计语言C++-精品课模板cs_第4页
面向对象程序设计语言C++-精品课模板cs_第5页
已阅读5页,还剩94页未读 继续免费阅读

下载本文档

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

文档简介

1、第七章第七章 类与对象类与对象丘志杰丘志杰电子科技大学电子科技大学计算机学院计算机学院 软件学院软件学院2022-2-42C+与与C最大的不同在于最大的不同在于C+增加了增加了面向对象面向对象的概念。的概念。C+允许用户定义允许用户定义新的抽象数据类型新的抽象数据类型类类型类类型,它将一,它将一组数据和与这些数据相关的操作封装组数据和与这些数据相关的操作封装在一起,实现了面向对象技术中的核在一起,实现了面向对象技术中的核心概念心概念数据封装数据封装。2022-2-43 抽象是对具体对象(问题)进行概括,抽象是对具体对象(问题)进行概括,抽出这一类对象的抽出这一类对象的公共性质公共性质并加以描述

2、并加以描述的过程。的过程。先注意问题的本质及描述,其次是实现过先注意问题的本质及描述,其次是实现过程或细节。程或细节。数据抽象:描述某类对象共有的属性或状数据抽象:描述某类对象共有的属性或状态。态。行为抽象:描述某类对象共有的行为特征行为抽象:描述某类对象共有的行为特征或具有的功能。或具有的功能。抽象抽象2022-2-44抽象实例抽象实例:时钟:时钟 数据抽象:数据抽象:具有表明当前时间的具有表明当前时间的时、分、秒时、分、秒 行为抽象:行为抽象:具有具有设置时间设置时间和和显示时间显示时间两个最两个最基本的功能基本的功能2022-2-45抽象实例抽象实例:人人数据抽象:数据抽象:姓名、年龄、

3、性别等姓名、年龄、性别等行为抽象:行为抽象:生物属性:吃饭、穿衣、睡觉、行走等行为生物属性:吃饭、穿衣、睡觉、行走等行为社会属性:工作、学习等行为社会属性:工作、学习等行为2022-2-46在研究问题时,侧重点不同,可能会产生在研究问题时,侧重点不同,可能会产生不同的抽象结果;解决同一问题时要求不不同的抽象结果;解决同一问题时要求不同,也会产生不同的抽象结果。例如:同,也会产生不同的抽象结果。例如:如果开发一个人事管理软件,那么关心的是员工的如果开发一个人事管理软件,那么关心的是员工的姓名、性别、工龄、工资、工作部门等相关信息。姓名、性别、工龄、工资、工作部门等相关信息。如果开发学籍管理软件,

4、那么关心的是学生的姓名、如果开发学籍管理软件,那么关心的是学生的姓名、性别、年龄、籍贯、所在学院等相关信息。性别、年龄、籍贯、所在学院等相关信息。因此,抽象是相对,而非绝对的。因此,抽象是相对,而非绝对的。2022-2-47如何实现抽象?如何实现抽象? 抽象定义了一个事物的本质特征,那么抽象定义了一个事物的本质特征,那么从软件设计的角度又如何对抽象出来的从软件设计的角度又如何对抽象出来的结果进行描述呢?结果进行描述呢?封装可以实现抽象。封装可以实现抽象。 封装就是将封装就是将数据和操作这些数据的函数数据和操作这些数据的函数进行有机地结合。进行有机地结合。 C+的解决方案:的解决方案:用类来实现

5、封装机制用类来实现封装机制2022-2-48定义和使用类的基本过程定义和使用类的基本过程 第一步:进行抽象第一步:进行抽象 第二步:定义类第二步:定义类 第三步:实现类第三步:实现类 第四步:使用类第四步:使用类2022-2-49类的定义:类的成员构成类的定义:类的成员构成class ClassName数据成员数据成员函数成员函数成员; 类是一种抽象数据类型,声明形式如下:类是一种抽象数据类型,声明形式如下:关键字关键字class用于声用于声明一个类类型明一个类类型用于表达数据抽象用于表达数据抽象用于表达行为抽象用于表达行为抽象2022-2-410类定义举例:时钟类类定义举例:时钟类class

6、 Clockint Hour, Minute, Second;void SetTime( int h, int m, int s ); void ShowTime( );2022-2-411类成员的访问控制类成员的访问控制 什么是什么是“类内类内”和和“类外类外” 在类定义之内称为类内在类定义之内称为类内 在类定义之外称为类外在类定义之外称为类外 数据封装的目的就是数据封装的目的就是信息隐蔽信息隐蔽。为了达到信。为了达到信息隐蔽,在息隐蔽,在C+类中,并非所有的成员都是类中,并非所有的成员都是对外可见的(或者说,是类外可以访问的)。对外可见的(或者说,是类外可以访问的)。 通过设置成员的通过设

7、置成员的访问控制属性访问控制属性来实现对类成来实现对类成员的访问控制。这些控制属性有:员的访问控制。这些控制属性有:public、protected、private2022-2-412类的定义:对成员的访问控制类的定义:对成员的访问控制class ClassNamepublic:公有成员公有成员protected:保护成员保护成员private:私有成员私有成员;2022-2-413公有成员公有成员在关键字在关键字public后面声明,它们是类与后面声明,它们是类与外部的接口,任何外部的接口,任何类内、类外类内、类外函数函数都可都可以访问公有数据和函数。以访问公有数据和函数。class Clo

8、ckpublic: void SetTime( int h, int m, int s );/公有成员函数公有成员函数 void ShowTime( ); /公有成员函数公有成员函数;2022-2-414私有成员私有成员在关键字在关键字private后面声明,后面声明,只允许本只允许本类中的函数(类中的函数(即类内函数即类内函数)访问,而类)访问,而类外的任何函数都不能访问。外的任何函数都不能访问。class Clockprivate:int Hour, Minute, Second;/私有数据成员私有数据成员;2022-2-415保护成员保护成员在关键字在关键字protected后面声明后面

9、声明的数据成的数据成员或成员函数。与员或成员函数。与private类似,其差别类似,其差别表现在继承与派生时对派生类的影响不表现在继承与派生时对派生类的影响不同,在第八章中再描述。同,在第八章中再描述。2022-2-416类定义举例:时钟类类定义举例:时钟类class Clockpublic: void SetTime( int h, int m, int s ); void ShowTime( );private: int Hour, Minute, Second;2022-2-417类的实现类的实现 实现一个类,就是按照所设定的功实现一个类,就是按照所设定的功能语义去实现类中的每一个成员函

10、能语义去实现类中的每一个成员函数。数。2022-2-418class Clockprivate: int Hour, Minute, Second;public: void SetTime( int h, int m, int s ) Hour=h; Minute=m; Second=s; void ShowTime( ) cout“Current Time:” coutHour“:” Minute“:” Second endl;在类内实现成员函数,编译器按在类内实现成员函数,编译器按内联函数处理内联函数处理在类内实现成员函数,编译器按在类内实现成员函数,编译器按内联函数处理内联函数处理202

11、2-2-419class Clockprivate: int Hour, Minute, Second;public: void SetTime( int h, int m, int s );/给出函数原型给出函数原型 void ShowTime( ); /给出函数原型给出函数原型;void Clock:SetTime( int h, int m, int s ) Hour=h; Minute=m; Second=s;void Clock:ShowTime( )cout“Current Time:”coutHour“:” Minute“:” Second 公有成员函数名公有成员函数名(形参列表

12、形参列表); 对象的指针对象的指针-公有数据成员公有数据成员2022-2-422举例:一个比较完整的举例:一个比较完整的Clock类类/定义定义Clock类类class Clockprivate: int Hour, Minute, Second;public: void SetTime( int h, int m, int s); void addHour(int h); void addMinute(int m); void addSecond(int s); void ShowTime( ); ;2022-2-423/实现实现Clock类中的成员函数类中的成员函数void Clock:S

13、etTime( int h, int m, int s ) Hour=h; Minute=m; Second=s;void Clock:addHour( int h ) Hour += h; void Clock:addMinute( int m ) Minute += m; void Clock:addSecond( int s ) Second += s; void Clock:ShowTime( )cout“Current Time:”;coutHour“:” Minute“:” Secondendl;2022-2-424/使用使用Clock类类void main( )Clock clo

14、ck_1, clock_2;clock_1. SetTime( 9 , 5 , 25 );clock_2. SetTime( 15 , 16 , 45 );clock_1. addHour( 3 );clock_2. addMinute( 8 );clock_1. ShowTime( );clock_2. ShowTime( );程序输出:程序输出: Current Time:12:5:25 Current Time:15:24:452022-2-425总结:定义和使用类类型的过程总结:定义和使用类类型的过程 抽象:抽象:对事物进行抽象对事物进行抽象 定义类:定义类:根据抽象的结果定义类的特性

15、根据抽象的结果定义类的特性 实现类:实现类:实现类中成员函数的逻辑实现类中成员函数的逻辑 使用类:使用类:在程序中定义类的实例,使用在程序中定义类的实例,使用类的公有成员。类的公有成员。2022-2-426 在定义类时,把可以被外部访问的成员说在定义类时,把可以被外部访问的成员说明为明为public属性,作为外部访问类中成员属性,作为外部访问类中成员的接口。把不能被外部访问的成员说明为的接口。把不能被外部访问的成员说明为private或或protected属性。属性。私有成员私有成员公有成员公有成员类对外的接口类对外的接口保护成员保护成员2022-2-427请思考以下情况请思考以下情况 能调用

16、下面语句吗?能调用下面语句吗?clock_1.Hour=21; 如果将如果将ShowTime说明为说明为private属性,属性,还能调用如下语句吗?还能调用如下语句吗?clock_2.ShowTime();2022-2-428练习一练习一设计一个三角形类设计一个三角形类CTriangle,该类满足下,该类满足下述要求:述要求:a)有一个成员函数)有一个成员函数SetEdge,用于设置三,用于设置三角形的边。角形的边。b)有一个成员函数)有一个成员函数GetArea,用于获得三,用于获得三角形的面积。角形的面积。c)有一个成员函数)有一个成员函数GetCircumference,用,用于获得三

17、角形的周长。于获得三角形的周长。在在main函数中,实例化一个函数中,实例化一个Ctriangle类的类的对象,将三条边分别为对象,将三条边分别为3、4、5,然后将,然后将其面积和周长显示在屏幕上。其面积和周长显示在屏幕上。2022-2-429备注:备注:1三角形面积的计算方式如下:三角形面积的计算方式如下: a、b、c分别为三条边,分别为三条边,S代表面积,代表面积,p=(a+b+c)/2,那么,那么S2=p(p-a)(p-b)(p-c)。2求开平方的库函数是求开平方的库函数是sqrt,需要包含,需要包含math.h头文件,使用方式的举例如下:头文件,使用方式的举例如下:int a, b;

18、b=36; a=sqrt(b); 那么那么a的值为的值为62022-2-430练习二练习二Need To Do2022-2-431几点说明几点说明 在声明类时,具有不同访问属性的成员可以按任在声明类时,具有不同访问属性的成员可以按任意顺序出现。意顺序出现。class Clockprivate: int Hour, Minute, Second;public: void SetTime( int h, int m, int s ); void ShowTime( );protected:;2022-2-432 修饰访问属性关键字可以多次出现。修饰访问属性关键字可以多次出现。class Clock

19、public: void SetTime( int h, int m, int s ); private: int Hour, Minute, Second;public: void ShowTime( );2022-2-433 一个成员只能具有一种访问属性,否则会出现歧异一个成员只能具有一种访问属性,否则会出现歧异。class Clockpublic: void SetTime( int h, int m, int s ); void ShowTime( );private: void ShowTime( );int Hour, Minute, Second;2022-2-434例子:简单例

20、子:简单int数组类数组类/数组类的定义数组类的定义const int ARRAY_SIZE=4;class MyArrayint dataARRAY_SIZE;public:int getArraySize();int setVal(int pos,int val);int getMaxVal();int getMinVal();2022-2-435/数组类的实现数组类的实现int MyArray:getArraySize()return ARRAY_SIZE;int MyArray:setVal(int pos,int val)if(posARRAY_SIZE)return -1;data

21、pos=val;return 0;2022-2-436/数组类的实现数组类的实现(续续)int MyArray:getMaxVal()int temp=data0; for(int i=1;itemp)temp=datai;return temp;int MyArray:getMinVal()int temp=data0; for(int i=1;iARRAY_SIZE;i+)if(dataitemp)temp=datai;return temp;2022-2-437/数组类的使用数组类的使用int main()MyArray array;int i,size,v,max,min;size=a

22、rray.getArraySize();coutplease input size numbers:endl; for(i=0;iv;array.setVal(i,v);max=array.getMaxVal();min=array.getMinVal();coutmax value is : maxendl;coutmin value is : minendl;return 0;2022-2-438改造:为简单改造:为简单int数组类增加公用的私有函数数组类增加公用的私有函数/数组类的定义:增加公用的私有函数数组类的定义:增加公用的私有函数const int ARRAY_SIZE=4;cla

23、ss MyArrayint dataARRAY_SIZE;int getVal(int condition);public:int getArraySize();int setVal(int pos,int val);int getMaxVal();int getMinVal();2022-2-439/数组类的实现:增加和调用公用的私有函数数组类的实现:增加和调用公用的私有函数int MyArray:getVal(int condition)int temp=data0; for(int i=1;itemp)temp=datai;elseif(datai SetTime( 9 , 5 , 25

24、 );p- ShowTime( );p- SetTime( 10 , 3 , 28 );p- ShowTime( );2022-2-442关键字关键字this C+为每个为每个非静态成员函数非静态成员函数提供一个提供一个this指针。指针。 this指针是一个指针是一个隐含的指针隐含的指针,它指向了正,它指向了正在被成员函数操作的那个对象。在被成员函数操作的那个对象。 this指针不能显式声明,它只是非静态成指针不能显式声明,它只是非静态成员函数的一个形参。员函数的一个形参。2022-2-443this指针举例指针举例class Counterint value;public:void set

25、Value( int value )this-value=value;class Counterint value;public:void setValue( int v )value=v;void main() Counter obj1,obj2;obj1.setValue(1);obj2.setValue(2);2022-2-444class Counterint value;public: void setValue(Counter *this, int v )this-value=v;class Counterint value;public:void setValue( int v

26、)value=v;void main() Counter obj1,obj2;obj1.setValue(1);obj2.setValue(2);编译器做了特殊处理编译器做了特殊处理void main() Counter obj1,obj2;obj1.setValue(&obj1,1);obj2.setValue(&obj2,2);2022-2-445构造函数和析构函数构造函数和析构函数 类的数据成员是不能在定义时直接类的数据成员是不能在定义时直接初始化的,以初始化的,以Clock类为例:类为例:class Clockprivate: int Hour=0, Minute=0,

27、 Second=0;/错误错误;2022-2-446 当当Clock类被实例化时,如何初始化对象的类被实例化时,如何初始化对象的状态,即如何初始化状态,即如何初始化Hour、Minute、Second三个成员呢?一种可行的方式就是三个成员呢?一种可行的方式就是显式调用初始化函数。显式调用初始化函数。Clock clock1;clock1. SetTime(21, 34, 43); 但是这种方式存在一些不好的情况:但是这种方式存在一些不好的情况: 程序员可能会忘记调用程序员可能会忘记调用SetTime()函数,导函数,导致对象没有被初始化。致对象没有被初始化。2022-2-447构造函数构造函数

28、 实际上,我们更希望这个初始化工作实际上,我们更希望这个初始化工作能够自动进行。类的能够自动进行。类的构造函数构造函数提供了提供了这种这种自动化功能自动化功能。 构造函数是类的一种特殊成员,构造函数是类的一种特殊成员,函数函数名和类名相同,没有名和类名相同,没有返回类型,返回类型,可以可以有参数。当创建类的一个新对象时,有参数。当创建类的一个新对象时,构造函数被构造函数被自动调用自动调用,完成对象的初,完成对象的初始化工作。始化工作。2022-2-448例:为例:为Clock类添加构造函数类添加构造函数class Clockprivate: int Hour, Minute, Second;p

29、ublic:Clock(int h, int m, int s);2022-2-449构造函数初始化数据成员的两种方式构造函数初始化数据成员的两种方式 赋值语句的方式:赋值语句的方式:Clock(int h, int m, int s) Hour = h;Minute = m; Second = s; 表达式表的方式:表达式表的方式:Clock(int h, int m, int s): Hour(h), Minute(m), Second(s) 2022-2-450 如果构造函数带有参数,那么在创建对象如果构造函数带有参数,那么在创建对象时必须给出对应的实参。时必须给出对应的实参。 如果构造

30、函数仅有一个参数:如果构造函数仅有一个参数:className obj = parameter; 如果构造函数有一个或多个参数:如果构造函数有一个或多个参数:className obj(parameter list); 如果构造函数有参数,但是在创建对象时如果构造函数有参数,但是在创建对象时又不给出对应的实参,此时编译出错。又不给出对应的实参,此时编译出错。传给构造函数实参的两种方式传给构造函数实参的两种方式2022-2-451void main( )Counter counter1(8);Counter counter2=9;Clock clock1(3, 5, 1);Clock clock

31、2( );/错误错误class Counterprivate:int value;public:Counter(int v):value(v) ;举例举例class Clockprivate: int Hour, Minute, Second;public: Clock(int h, int m, int s);2022-2-452重载构造函数重载构造函数 一个类可以提供多个构造函数,但它们的一个类可以提供多个构造函数,但它们的参数表必须不同。重载的目的是为了参数表必须不同。重载的目的是为了满足满足不同的初始化需要不同的初始化需要。class Clockprivate: int Hour,Mi

32、nute, Second;public:Clock(int h, int m, int s);Clock( );Clock(char *timestr);void main( )Clock clock1(23, 12, 0);Clock clock2( );Clock clock3(“14:45:32” );2022-2-453具有缺省参数的构造函数具有缺省参数的构造函数 构造函数也可以有缺省参数。如果在类外构造函数也可以有缺省参数。如果在类外实现该函数时,就不能再说明缺省值了。实现该函数时,就不能再说明缺省值了。class Clockprivate: int Hour,Minute, Sec

33、ond;public:Clock(int h = 0, int m = 0, int s = 0);Clock(const char *timestr);2022-2-454缺省的构造函数缺省的构造函数 对于没有构造函数的类,对于没有构造函数的类,编译器将会自编译器将会自动为它生成一个没有参数的构造函数,动为它生成一个没有参数的构造函数,该函数该函数不做任何工作不做任何工作。class Clockprivate: int Hour, Minute, Second;2022-2-455析构函数析构函数 与构造函数相对的是析构函数。与构造函数相对的是析构函数。C+通过析通过析构函数来处理对象被销毁

34、时的清理工作。构函数来处理对象被销毁时的清理工作。 析构函数没有返回类型,没有参数,函数名析构函数没有返回类型,没有参数,函数名是在类名前加是在类名前加“”。 析构函数将会在析构函数将会在对象的生存期结束后对象的生存期结束后被被自动自动调用调用。 如果没有进行显式说明,系统将会生成一个如果没有进行显式说明,系统将会生成一个不做任何事的缺省的析构函数。不做任何事的缺省的析构函数。2022-2-456举例:为举例:为Clock类添加析构函数类添加析构函数class Clockprivate: int Hour, Minute, Second;public: Clock(int h=12, int

35、m=0, int s=0);Clock( );Clock:Clock( )cout“Clock obj destroyed!”endl;2022-2-457void func( )Clock obj1,obj2;void main()func();/输出:输出: Clock obj destroyed! Clock obj destroyed!2022-2-458析构函数的典型用法析构函数的典型用法class MyStringprivate: int len;char *buf;public: MyString(int n);void copy(char *src);MyString:MySt

36、ring( int n)len=n;buf=new charn;void MyString:copy(char *src)strcpy(buf,src);void func()MyString obj( 64 );obj.copy(“helloworld”);void main()func( );!此时,!此时,obj的的buf所指向的所指向的内存空间没有释放内存空间没有释放2022-2-459class MyStringprivate: int len;char *buf;public: MyString(int n); MyString( );void copy(char *src);My

37、String:MyString( int n)len=n;buf=new charn;void MyString:copy(char *src)strcpy(buf,src);MyString: MyString( )delete buf;void func()MyString obj( 64 );obj.copy(“helloworld”);void main()func( );!当!当obj对象被释放时,析构对象被释放时,析构函数被自动调用,函数被自动调用,buf所指所指向的内存空间被释放向的内存空间被释放2022-2-460拷贝构造函数拷贝构造函数 构造函数的参数可以是任意类型,如果构造

38、函数的参数可以是任意类型,如果将与将与自己同类的对象的引用自己同类的对象的引用作为参数时,作为参数时,该构造函数就称为该构造函数就称为拷贝构造函数拷贝构造函数。 拷贝构造函数的特点:拷贝构造函数的特点: 首先,它是一个构造函数,当创建对象时首先,它是一个构造函数,当创建对象时系统会自动调用它。系统会自动调用它。 其次,它将一个已经创建好的对象作为拷其次,它将一个已经创建好的对象作为拷贝构造函数的参数,并根据需要将该对象贝构造函数的参数,并根据需要将该对象中的数据成员逐一对应地赋值给新对象。中的数据成员逐一对应地赋值给新对象。2022-2-461示例示例class Pointprivate: f

39、loat x, y;public: Point(float a, float b) x=a; y=b; Point(Point &obj)x=obj.x;y=obj.y; ;void main()Point obj1( 5, 15);/调用调用Point(float , float )Point obj2(obj1);/调用调用Point(A&)Point obj3=obj2;/调用调用Point(A&)2022-2-462缺省的拷贝构造函数的应用缺省的拷贝构造函数的应用 如果一个类没有定义拷贝构造函数,那么如果一个类没有定义拷贝构造函数,那么C+编译器会为该类产生一个

40、编译器会为该类产生一个缺省的拷贝构缺省的拷贝构造函数造函数。缺省的拷贝构造函数使用。缺省的拷贝构造函数使用位拷贝的位拷贝的方法方法来完成对象到对象的复制。也就是说,来完成对象到对象的复制。也就是说,将第一个对象中的数据成员的值将第一个对象中的数据成员的值原封不动原封不动拷拷贝到第二个对象的数据成员中。贝到第二个对象的数据成员中。2022-2-463例:缺省的拷贝构造函数的应用例:缺省的拷贝构造函数的应用class Pointprivate: float x, y;public: Point(float a, float b) x=a; y=b; ;void main()Point obj1(

41、5, 15); /调用调用A(float, float)Point obj2(obj1); /调用缺省的拷贝构造函数调用缺省的拷贝构造函数Point obj3=obj2; /调用缺省的拷贝构造函数调用缺省的拷贝构造函数obj2是是obj1的精确拷贝,的精确拷贝,obj3是是obj2的精的精确拷贝确拷贝2022-2-464缺省的拷贝构造函数的缺点缺省的拷贝构造函数的缺点 在大多数情况下,缺省拷贝构造函在大多数情况下,缺省拷贝构造函数工作得很好,但在一些特殊的场数工作得很好,但在一些特殊的场合,它的表现将不尽人意。合,它的表现将不尽人意。2022-2-465class MyStringprivat

42、e: int len;char *buf;public: MyString(int n);MyString( );void copy(char *src);MyString:MyString( int n)len=n;buf=new charn;void MyString:copy(char *src)strcpy(buf,src);MyString:MyString( )delete buf;void func()MyString obj1( 64 );obj1.copy(“helloworld”); MyString obj2=obj1;void main()func( );! 由于调用的

43、是默认的拷贝由于调用的是默认的拷贝构造函数,因此构造函数,因此obj1和和obj2中的中的buf指向同一内存指向同一内存空间,当它们被释放时,空间,当它们被释放时,该内存空间将被释放两次。该内存空间将被释放两次。2022-2-466改进办法:增加拷贝构造函数改进办法:增加拷贝构造函数class MyStringpublic: MyString(int n); MyString(MyString &obj); ;MyString:MyString(MyString &obj)len = obj.len;buf=new char len ;strcpy( buf , obj.buf

44、 );通过自定义拷贝构造函数,可以准确通过自定义拷贝构造函数,可以准确地复制数据,以免发生错误。地复制数据,以免发生错误。2022-2-467拷贝构造函数起作用的地方拷贝构造函数起作用的地方 拷贝构造函数除了在创建新对象时拷贝构造函数除了在创建新对象时被调用外,还在以下情况被调用:被调用外,还在以下情况被调用:对象作为函数参数对象作为函数参数函数返回对象函数返回对象2022-2-468举例举例class Counterprivate: int value;public: Counter(int v) value=v; void add(int v) value+=v; void show( )

45、 coutvalueendl; ;Counter func(Counter obj )obj.add(6);return obj;void main( ) Counter b1=5; Counter b2=func(b1); b1.show(); b2.show();输出:输出:5 112022-2-469 调用调用func(b1)时调用默认的拷贝构造函数时调用默认的拷贝构造函数 调用调用return obj时调用默认的拷贝构造函数时调用默认的拷贝构造函数 将将func()返回值赋给返回值赋给b2时调用默认的拷贝构时调用默认的拷贝构造函数造函数5b111temp11b25(11)objfunc

46、(b1)return objb2=func(b1)2022-2-470对象数组对象数组 与任何其它数据类型一样,可以创建与任何其它数据类型一样,可以创建一个类的对象数组。例如:一个类的对象数组。例如:Clock clocks10; 通过下标访问数组中的对象,进而访通过下标访问数组中的对象,进而访问该对象的公有成员,例如:问该对象的公有成员,例如:clocks3.ShowTime();2022-2-471举例举例class Pointpublic: float x,y; Point( )x=0;y=0; Point(float a)x=a;y=0; Point(float a ,float b)

47、x=a;y=b; void show( ) coutx“:”yendl; ;void main( ) Point array3;array1.x=5;array1.y=6;array1.show();输出:输出:5:62022-2-472对象数组的初始化对象数组的初始化 对象数组的初始化过程,实际上就对象数组的初始化过程,实际上就是是调用构造函数调用构造函数对每一个数组元素对每一个数组元素进行初始化的过程。进行初始化的过程。 如果在声明数组时给出每一个数组如果在声明数组时给出每一个数组元素的初始值,在初始化过程中就元素的初始值,在初始化过程中就会调用会调用最匹配最匹配的构造函数。的构造函数。2

48、022-2-473class Pointpublic: Point( )x=0;y=0; Point(float a)x=a;y=0; Point(float a , float b)x=a;y=b; ;void main( )Point array3= Point(3,4), 5 ;举例:对象数组初始化举例:对象数组初始化初始化初始化array0时调用的是时调用的是Point(float ,float)构造函数构造函数初始化初始化array1时调用的是时调用的是Point(float)构造函数构造函数初始化初始化array2时调用的是时调用的是Point( )构造函数构造函数2022-2-4

49、74对象指针的加减操作对象指针的加减操作class Counterprivate: int value;public: Counter(int v) value=v; void show( ) coutvalueshow();p+;p-show();p+;p-show();输出:输出:5 6 72022-2-475类类型作参数类型的三种方式类类型作参数类型的三种方式 对象本身作为参数对象本身作为参数 由于由于C+采用传值的方式传递参数,因此使用采用传值的方式传递参数,因此使用对象本身参数时,形参是实参的一个拷贝。在对象本身参数时,形参是实参的一个拷贝。在这种情况下,最好显式地为类定义一个拷贝构

50、这种情况下,最好显式地为类定义一个拷贝构造函数,以免出现不容易发现的错误。造函数,以免出现不容易发现的错误。2022-2-476举例举例:对象本身做函数参数对象本身做函数参数class Counterprivate: int value;public: Counter(int v) value=v; void add(int v) value+=v; void show( ) coutvalueadd(6);输出:输出:5 112022-2-479静态成员静态成员 当用关键字当用关键字static说明一个类成员时,说明一个类成员时,该成员称为静态成员。因此可以分为:该成员称为静态成员。因此可以

51、分为:静态数据成员静态数据成员静态成员函数静态成员函数2022-2-480静态数据成员静态数据成员class ABCD /声明静态数据成员声明静态数据成员static int s_value;int value;ABCD A ,B,C,D; 类的所有对象共享静态数据成员,因此无论建立多类的所有对象共享静态数据成员,因此无论建立多少个该类的对象,静态数据成员只有一份拷贝。少个该类的对象,静态数据成员只有一份拷贝。 静态数据成员属于类,而不属于具体的对象。静态数据成员属于类,而不属于具体的对象。2022-2-481静态数据成员的定义和初始化静态数据成员的定义和初始化 在类内只是静态数据成员的声明,

52、但是静态数据在类内只是静态数据成员的声明,但是静态数据成员必须在类外定义,格式如下:成员必须在类外定义,格式如下:类型类型 类名类名:静态数据成员静态数据成员int ABCD:s_value; 在定义静态数据成员的时候可以对其进行初始化,在定义静态数据成员的时候可以对其进行初始化,方式如下:方式如下:类型类型 类名类名:静态数据成员静态数据成员int ABCD:s_value=6;2022-2-482静态数据成员的使用静态数据成员的使用 静态数据成员也有静态数据成员也有public和和private之分,由之分,由于静态数据成员是属于类的,因此:于静态数据成员是属于类的,因此: 在类外,按如下

53、形式访问在类外,按如下形式访问public静态数据成员:静态数据成员: 类名类名:静态数据成员静态数据成员ABCD:s_value+; 在类内,可以直接访问所有属性的静态数据成员在类内,可以直接访问所有属性的静态数据成员 特别地,当类对象不存在时,也可以访问类特别地,当类对象不存在时,也可以访问类的静态数据成员。的静态数据成员。2022-2-483例例1:静态数据成员的基本用法:静态数据成员的基本用法class counterstatic int count;/声明声明 public:void setcount(int num)count=num;void showcount()coutcou

54、nt“ “;/定义定义int counter:count=0;void main()counter a, b;a.showcount();b.showcount();a.setcount(34);a.showcount();b.showcount();/输出:输出:0 0 34 342022-2-484静态成员函数静态成员函数 静态成员函数的定义静态成员函数的定义class ABCDpublic:static void show_staticvalue(); 静态成员函数只属于一个类,它没有静态成员函数只属于一个类,它没有this指针。指针。 静态成员函数也可以声明为静态成员函数也可以声明为p

55、ublic或或private属性。属性。2022-2-485请思考请思考 能将构造函数声明为非能将构造函数声明为非public属性吗?属性吗?如果能,将会出现什么情况?如果能,将会出现什么情况?class Clockprivate: int Hour, Minute, Second;Clock(int h, int m, int s);void main()Clock aclock(1,2,3);编译出错,因为构造函数编译出错,因为构造函数是是private属性属性2022-2-486举例:静态成员的应用举例:静态成员的应用 如果有一个类如果有一个类MyClass,如何设计才能保,如何设计才能

56、保证在程序运行中该类只能有一个实例?证在程序运行中该类只能有一个实例? 利用静态成员可以解决该问题。利用静态成员可以解决该问题。class MyClassprivate:static MyClass *instance;MyClass()public:static MyClass *getInstance() if(instance=NULL) instance=new MyClass(); return instance;MyClass *MyClass:instance=NULL;void main()MyClass *obj;obj=MyClass:getInstance();将构造函数

57、声明为非将构造函数声明为非public属性,可以控制对象的生成!属性,可以控制对象的生成!2022-2-487友元关系友元关系 封装的目的就是为了实现信息隐蔽。封装的目的就是为了实现信息隐蔽。 一个对象的私有成员只能被自己的成员访一个对象的私有成员只能被自己的成员访问到。当类外的对象或函数要访问这个类问到。当类外的对象或函数要访问这个类的私有成员时,只能通过该类提供的的私有成员时,只能通过该类提供的公有公有成员成员间接地进行。间接地进行。 出于效率(而非技术上必须)的考虑,出于效率(而非技术上必须)的考虑,C+提供了提供了友元机制友元机制来打破私有化的界限,来打破私有化的界限,即一个类的友元可

58、以访问到该类的私有成即一个类的友元可以访问到该类的私有成员。员。2022-2-488友元函数友元函数 问题的提出问题的提出Point类代表类代表“点点”,考虑如下需求:,考虑如下需求:需要一个函数来计算任意两点间的距离,需要一个函数来计算任意两点间的距离,那么这个函数该如何设计呢?那么这个函数该如何设计呢?class Pointfloat x, y;public:Point( float xx=0, float yy=0)x=xx;y=yy;float GetX( )return x;float GetY( )return y;2022-2-489解决方案解决方案1 将计算两点距离的函数设计为

59、类外的普通函数将计算两点距离的函数设计为类外的普通函数float Distance(Point a , Point b)float x1,x2,y1,y2,dx,dy;x1=a.GetX(); y1=a.GetY();x2=b.GetX(); y2=b.GetY();dx=x1-x2;dy=y1-y2;return sqrt(dx*dx+dy*dy);void main()Point p1(3.0, 5.0), Point p2(4.0, 6.0); float d=Distance(p1, p2); coutThe distance is ;coutdendl;/输出:输出: The dis

60、tance is 1.14212022-2-490 这种方案的缺点:这种方案的缺点: 因为类外函数是不能直接访问类中的私有成员的,因为类外函数是不能直接访问类中的私有成员的,因此该函数必须调用因此该函数必须调用GetX和和GetY公有成员函数先公有成员函数先获取获取“点点”的坐标,然后再计算两点距离,这种的坐标,然后再计算两点距离,这种方式是不太方便的。方式是不太方便的。 另一种方案就是将计算两点距离的函数设计成另一种方案就是将计算两点距离的函数设计成为为Point类的成员函数。虽然从语法的角度来类的成员函数。虽然从语法的角度来看这不难实现,但是理解起来却有问题:看这不难实现,但是理解起来却有问题: 距离反映的是两点之间的关系,它既不属于每一距离反映的是两点之间的关系,它既不属于

温馨提示

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

评论

0/150

提交评论