C++及Windows程序设计A:第03章 类和对象_第1页
C++及Windows程序设计A:第03章 类和对象_第2页
C++及Windows程序设计A:第03章 类和对象_第3页
C++及Windows程序设计A:第03章 类和对象_第4页
C++及Windows程序设计A:第03章 类和对象_第5页
已阅读5页,还剩136页未读, 继续免费阅读

下载本文档

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

文档简介

1、类和对象第03章主要内容3.2 类和对象3.3 构造函数和析构函数3.4 对象数组、指针、引用3.5 静态成员3.6 友元3.7 对象成员3.1 面向对象概述1、对象的概念称现实世界中客观存在的事物为对象,整数是一个对象,平面上的点是一个对象,河流湖泊都是对象。复杂的对象可以由简单的对象组成,例如火车站对象又包含售票处、行李房、信号灯、站台、铁轨和通信设施等对象。对象是构成世界的一个独立单位,具有:静态特征:可以用某种数据来描述动态特征:对象所表现的行为或具有的功能对象的概念面向对象方法中的对象是系统中用来描述客观事物的一个实体,它是用来构成系统的一个基本单位。对象由一组属性和一组行为构成。属

2、性:用来描述对象静态特征的数据项。行为:用来描述对象动态特征的操作序列。属性和行为的代码封装在称为类的程序实体中。对象的概念售票处有各种规格的车票,这些车票表示售票处的静态特征。它提供发售车票的功能(操作),表示了售票处的动态特征。C+可使用对象名、属性和操作三要素来描述对象。对象名用来标识一个具体对象。用数据来表示对象的属性。操作是描述对象动态特征(行为)的一个函数序列(使用函数实现操作),也称为方法或服务。2、对象的结构对象的结构用简单对象表示平面上的A(1.5,5.4)和B(3.5,6.9)两个坐标点。对象名是“A”,A是一个点的对象的名称。用x坐标和y坐标表示坐标点对象的静态属性(称为

3、位置属性)。假设暂且让点对象对外有显示属性值、设置属性值和移动位置等操作,这里分别使用函数display,setxy,move来实现这些操作。对象的结构3、抽象和类抽象是一种从一般的观点看待事物的方法,即集中于事物的本质特征,而不是具体细节或具体实现。可以将一组对象的共同特征进一步抽象出来,从而形成“类”的概念。例如,从点A和点B抽象出点的概念,这就是“点类”。这个类的本质是具有两个坐标属性和对这两个属性值进行操作的方法。A和B的区别只是属性值的不同,其方法是相同的。抽象和类通过分析一组对象(A和B),抽取公共的行为将其放入到一个类中,取名为Point类,并用下图的Point类模型表示它。它由

4、类名、一组属性和一组操作等3部分组成。类的属性只是性质的说明,对象的属性才是具体的数据。所以,Point类只是表示类名是Point,它的点位置是两个实数,但还没有具体的位置。只有像点A和点B等具体对象,才具有确定的属性值,它们是Point类的具体对象,称它为类Point的一个实例。抽象和类抽象和类对于一个具体的类,它有许多具体的个体,这些个体叫做“对象”。举个例子,“人”是一个类,具有“直立行走、会使用工具”等一些区别于其他事物的共同特征;而张三、李四、王五等一个个具体的人,就是“人”这个类的一个个“对象”,同一类的不同对象具有相同的行为方式,不同类的对象具有不同的行为。这种设计方法模仿了人们

5、建立现实世界模型的方法,与人们认识客观事物的过程相一致,提高了编写程序的质量和可靠性。抽象和类在程序中,每个对象需要有自己的存储空间以保存它们自己的属性值。所谓“一个类的所有对象具有相同的属性”,是指属性的个数、名称、数据类型相同,各个对象的属性值则可以互不相同,并且随着程序的执行而变化。至于操作,则是所有对象共同使用它们的类定义中给出的操作代码,在C+中,每个操作是一个“成员函数” 。4、封装和数据隐藏举个简单的例子,电视机把各种部件都装在机箱里,遥控功能装在遥控器盒子中。用户通过遥控器操作电视机,既方便了用户,也保护了电视机。将类封装起来,也是为了保护类的安全,所谓安全,就是限制使用类的属

6、性和操作。按照面向对象的封装原则,对象的属性只能由这个对象的操作来存取。封装和数据隐藏对象的操作分为内部操作和外部操作。外部操作对外提供一个接口,通过这个接口接收外部的消息并提供操作(服务)。对象内部数据结构的这种不可访问性称为信息(数据)隐藏。数据封装给数据提供了与外界联系的标准接口,只有通过这些接口,才能访问这些数据。程序员总是和接口打交道,不必了解数据的具体细节。封装就是把对象的属性和操作结合成一个独立的系统单位,并尽可能隐蔽内部细节。封装和数据隐藏封装要求一个对象应具备明确的功能,并具有接口以便和其他对象相互作用。同时,对象的内部实现(代码和数据)是受保护的,外界不能访问它们。封装使得

7、一个对象可以像一个部件一样用在各种程序中。数据封装一方面使得程序员在设计程序时可以专注于自己的对象,“各人自扫门前雪,莫管他人瓦上霜”,同时也切断了不同模块之间数据的非法使用,减少了出错的可能性。5、继承的概念继承是一个对象可以获得另一个对象的特性的机制,它支持层次类这一概念,例如红香蕉苹果属于苹果类,而苹果类又属于水果类。通过继承,低层的类只需定义特定于它的特征,而共享高层的类中的特征。继承具有重要的实际意义,它简化了人们对事物的认识和描述。比如我们认识了轮船的特征之后,知道客轮是轮船的特殊种类,它具有轮船的特征。当研究客轮时,只要把精力用于发现和描述客轮独有的那些特征即可。继承的概念 好处

8、:可增强程序代码的可重用性。如研究生是学生类的派生类,学生类拥有“学号”、“姓名”、“学校名称”等属性,研究生类只需增加“导师”、“专业方向”,会继承基类中的所有属性。便于代码维护,编写研究生类时,不用关心学生类的实现,只是增加自己的代码。6、多态性的概念多态是指在一般类中定义的属性或行为,被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为。这使得同一个属性或行为在一般类及其各个特殊类中具有不同的语义。例如:数的加法-实数的加法 -复数的加法主要内容3.2 类和对象3.3 构造函数和析构函数3.4 对象数组、指针、引用3.5 静态成员3.6 友元3.7 对象成员3.1 面向对象概述C+

9、中的类从程序员的角度,类是一种用户自定义数据类型,对象是用类这种数据类型定义的变量。每个类中包含数据和对数据进行操作的函数,数据用来描述对象的属性,函数表示对象具有的行为。类中的数据和函数称为成员,数据部分称为数据成员,函数称为成员函数。1、类的定义语法class 类名称private:私有数据成员和私有成员函数说明protected:保护数据成员和保护成员函数说明public:共有数据成员和共有成员函数说明;/成员函数的实现部分定义部分类的定义语法class CDogint age;float weight;void SetAge(int a);int GetAge();/成员函数的实现部分

10、数据成员,定义类的属性成员函数,定义类的行为类的定义语法class CDog /常以大写字母开头void SetAge(int a) age=a; int GetAge();int CDog:GetAge() return age; 成员函数的实现常放在类定义之外短小函数可置定义中在头文件中定义类在头文件中定义类在CPP文件中实现类的方法在CPP文件中实现类2、定义对象的基本方式类定义了所有对象应该具备的属性和行为;类只是抽象概念程序是由各种对象构成的由类定义对象:类名 对象名;#include “dog.h”void main()CDog myDog;包含CDog类定义的头文件操纵对象调用对

11、象的方法控制对象的行为调用对象的成员函数myDog.wow(); 成员的访问控制(类定义时决定)public:通过对象可以访问的成员,通常将成员函数声明在public下;private:通过对象不能访问的成员,通常将数据成员声明在private下;myDog.SetAge(4); myDog.age=5;CDog.SetAge(4);XX操纵对象公有成员是对象对外的“接口”,私有成员被隐藏在类内部。 私有数据成员公有成员,对外的“接口”3、完整示例头文件dog.hclass CDogprivate:int age;public:void SetAge(int a)age=a;int GetAg

12、e();void wow();void print_age();完整示例头文件dog.cpp#include dog.h#include using namespace std;int CDog:GetAge() return age; void CDog:wow()coutIm a lovely dog!endl;void CDog:print_age()coutIm age years old.endl;完整示例主程序main.cpp#include dog.h#include using namespace std;void main()CDog dog1,dog2;dog1.SetAg

13、e(3);dog1.wow();dog1.print_age();dog2.SetAge(5);coutdog2.GetAge()endl;运行结果Im a lovely dog!Im 3 years old.54、类和对象进一步说明定义类只是类型说明,定义类时不能对数据成员进行初始化class CDogprivate:int age=1; ;X此时只是定义CDog类型,并不存在具体的小狗类和对象进一步说明通过对象只能访问公有成员在类的成员函数数体内,可以随意调用所有类型的数据成员和成员函数。而通过对象只能借助公有接口间接访问私有数据成员。CDog myDog;myDog.age=4;void

14、 CDog:print_age() coutIm age years old.endl;X类和对象进一步说明成员函数的实现放在类定义内部,自动编译为内联函数(只适用于短小函数);如果放在类定义外部,使用关键字inline才能编译为内联函数。inline void CDog:print_age() coutIm age years old.公有成员;CDog myDog;CDog *pDog=&myDog; pDog-SetAge(6); pDog-print_age();对象指针存储的是对象在内存中的首地址,本身只占用4个字节。对象引用的成员访问对引用的访问,与对象的访问完全相同。引用和对象占

15、用相同的存储空间,实际上是同一个东西。CDog dog2;CDog &rDog=dog2;rDog.SetAge(3);对象定义时的内存分配CDog dog1,dog2;dog1.SetAge(2);dog2.SetAge(3);每个对象有各自的数据成员,取值各不相同,成员函数代码只有1份。2dog1dog23ageagewowSetAge分工与协作类设计者:完成类的定义与各成员函数的实现,进一步形成类库。主程序设计者:完成程序的主要逻辑,利用别人完成的类定义各种对象,通过消息和接口控制各对象模拟现实世界。主要内容3.2 类和对象3.3 构造函数和析构函数3.4 对象数组、指针、引用3.5 静

16、态成员3.6 友元3.7 对象成员3.1 面向对象概述1、什么是构造函数?类的特殊成员函数;函数名与类名相同;不能有返回类型,void也不行;构造函数访问权限必须为公有,但不应该被显式调用;构造函数通常会重载,有多个实现版本。构造函数的目的:构建对象时,由系统自动调用,用于初始化对象数据成员。CDog中没有构造函数?如果在类定义时没有定义构造函数,编译系统会自动生成一个默认构造函数。Class CDogint age;public:CDog() ;编译系统提供的没有实质功能的默认构造函数写自己的构造函数在定义类时可以提供多个版本(重载)的构造函数。但只要你实现任意一个版本的构造函数,编译器便不

17、再提供默认构造函数。一个完整的类通常会实现以下三种构造函数无参数构造函数带参数构造函数拷贝构造函数2、缺省构造函数class CDogpublic: CDog() age=1; cout“constructor 1”endl; CDog(int a)age=a;cout“constructor 2”endl; void print_age() private: int age;缺省构造函数void main()CDog dog1;dog1.print_age();CDog dog2(4);dog2.print_age();/CDog dog3(); 运行结果constructor 1Im 1

18、years old.constructor 2Im 4 years old.X重载还是带默认参数?class CDogpublic: CDog(int a=1) age=a;cout“constructor 2”endl; void print_age() private: int age; 实现相同的功能避免同时使用重载或默认参数!默认参数常在成员函数原型中指定。3、拷贝构造函数class CDogpublic: CDog(int a=1)age=a;cout“constructor 1”endl; CDog( const CDog& dog) age=dog.age; cout“const

19、ructor 2”endl; void print_age() private: int age;使用const,防止dog被意外修改;在构造函数中可以通过dog对象访问私有成员age定义和dog1一样的dog2void main()CDog dog1(4);dog1.print_age();CDog dog2(dog1);dog2.print_age();运行结果constructor 1Im 4 years old.constructor 2Im 4 years old.CDog dog2=CDog(dog1);CDog dog2=dog1;默认拷贝构造函数如果没有定义拷贝构造函数,编译系

20、统自动生成一个默认拷贝构造函数class CDogpublic:CDog(const CDog& dog)age=dog.age;依次为所有数据成员赋值,当含指针成员时,容易出问题4、构造函数的调用时机掌握构造函数的难点何时调用定义对象new动态创建对象调用函数,对象进行值传递函数返回对象,进行值传递要点:构造函数由系统自动调用。全局对象的构造函数在main函数之前调用!对象作为函数参数到底调用几次构造函数?void fun( CDog dog)dog.print_age();void main()CDog dog1; fun(dog1);第1次:定义对象第2次:实参与形参结合每次调用相当于定

21、义局部变量对象作为函数返回值CDog Copy( CDog dog)CDog dog1;dog1=dog;return dog1;void main()CDog dog2(4);CDog dog3;dog3=Copy(dog2);dog3.print_age();第1次:定义对象第2次:定义对象第3次:参数传递第4次:定义对象第5次:返回临时对象“=” 赋值还是初始化? CDog dog2=dog1; CDog dog2(dog1); CDog dog2=CDog(dog1); CDog dog2=CDog(4); CDog dog2; dog2=dog1; CDog dog2; dog2=C

22、Dog(4); 构造函数调用1次 构造函数调用1次 构造函数调用1次 构造函数调用1次 赋值,让dog2与dog1一样 赋值,构造函数调用2次int a=5;int a;a=5;5、类型转换构造函数class Complexdouble real, image;public:Complex(double r,double i) real=r; image=i; Complex(double r);类型转换构造函数Complex:Complex(double r) real=r; image=0;void main() Complex c; c = 4;40realimage6、什么是析构函数类

23、的特殊成员函数;函数名为类名称;不能有返回类型,void也不行;析构函数不能有参数,析构函数只能有一个版本,不能重载。析构函数也必须是public类型。析构函数的目的:在删除对象或对象超出生存期时,由系统自动调用,完成清理工作。CDog中没有析构函数?如果在类定义时没有定义析构函数,编译系统会自动生成一个默认析构函数。Class CDogint age;public:CDog() ;编译系统提供的没有实质功能的默认析构函数写自己的析构函数在定义类时,可以自己定义析构函数,以完成特定的释放清理工作,通常情况下在构造函数中使用new分配内存空间,析构函数中需要用delete释放。CDog:CDog

24、() coutDestructorendl;析构函数的调用时机析构函数的调用由系统自动完成对象超出其生存期,如函数内部定义的局部对象,随着函数的返回而析构new动态创建对象,调用delete析构函数调用返回临时对象,在执行下一条语句时被析构多个对象析构的顺序和定义它们时构造的顺序相反。析构的次数CDog Copy(CDog dog)CDog dog1;dog1=dog;return dog1;void main()CDog dog2(4);CDog dog3;dog3=Copy(dog2);dog3.print_age();运行结果DestructorDestructorDestructorI

25、m 4 years old.DestructorDestructor主要内容3.2 类和对象3.3 构造函数和析构函数3.4 对象数组、指针、引用3.5 静态成员3.1 面向对象概述3.6 友元3.7 对象成员回顾CDog类定义class CDogpublic: CDog() age=1; cout“constructor 1”endl; CDog(int a)age=a;cout“constructor 2”endl; void print_age() private: int age;1、对象数组及初始化void main()CDog MyDogs2=CDog(2),CDog(4);for

26、(int i=0;i2;i+)MyDogsi.print_age();不指定初始化列表,要提供缺省构造函数共调用构造函数2次对象数组及初始化void main()CDog MyDogs10;for(int i=0;i10;i+)MyDogsi.print_age();共调用缺省构造函数10次使用对象指针访问对象数组元素void main()CDog MyDogs10;CDog *pDog=MyDogs;for(int i=0;iprint_age();pDog+;指向数组中下一个元素动态分配对象数组动态申请数组CDog *pDog=new CDog5;/创建5条小狗,但无法显式初始化,类必须要

27、提供无参数的构造函数!动态创建的对象数组一定要用delete释放delete pDlg;2、指针和引用的效率用对象作为函数参数和返回值时形参与实参结合,调用构造函数;函数返回时,构造临时对象;函数返回后,局部对象和临时对象需要被析构;与结构体变量作为参数类似,调用效率低,解决的方法对象引用和对象指针对象引用作为参数void fun(CDog& dog)dog.print_age();void main()CDog dog2(4);fun(dog2);运行结果constructorIm 4 years old.dog是dog2的引用,是同一个东西引用作为函数返回值CDog& fun(CDog&

28、dog)dog.SetAge(5);return dog;void main()CDog dog2(4), CDog dog3;dog3=fun(dog2);dog3.print_age();运行结果constructorconstructorIm 5 years old.dog2、dog以及返回的临时引用为同一个东西引用的陷阱CDog& fun()CDog dog1(4);return dog1;void main()CDog dog2;dog2=fun();dog2.print_age();运行结果constructorconstructorIm 4199184 years old.局部对

29、象dog1在函数返回后将要释放对象指针作为函数参数void fun(CDog *dog1)dog1-print_age();void main()CDog dog2(4);fun(&dog2);运行结果constructorIm 4 years old.dog2420002000dog1对象指针作为函数返回值CDog* fun()CDog *dog1=new CDog(4);return dog1;void main()CDog *dog2;dog2=fun();dog2-print_age();delete dog2;运行结果constructorIm 4 years old.4200020

30、00dog2指针的陷阱CDog* fun()CDog dog1(4);return &dog1;void main()CDog *dog2;dog2=fun();dog2.print_age();运行结果constructorIm 1244964 years old.4dog120002000dog2回头看拷贝构造函数class CDogpublic: CDog(int a=1)age=a;cout“constructor 1”endl; CDog( const CDog& dog) age=dog.age; cout“constructor 2”endl; void print_age()

31、private: int age;3、指针成员小狗的名字class CDogprivate:char *name; /char name20; 可行但不好public:CDog(char *pName);/CDog(const CDog &dog);CDog();void print_name();内存的分配与释放CDog:CDog(char *pName)name=new charstrlen(pName)+1;if(name)strcpy(name,pName);CDog:CDog()delete name;?内存的分配与释放#include #include using namespac

32、e std;void main()CDog dog1(“snoopy”);dog1.print_name(); dog1局部变量:(栈中) 构造函数:堆中分配空间 main结束,析构函数,释放堆中空间危险的默认拷贝构造函数系统自动生成的构造函数CDog:CDog(const CDog& dog)name=;void main()CDog dog1(“snoopy”);CDog dog2(dog1);危险! 此时dog1和dog2指向同一个字符串浅拷贝void fun(CDog dog) ; /什么也不做void main()CDog dog1 (“snoopy”);dog1.p

33、rint_name();fun(dog1);dog1.print_name();dognamedog1namesnoopy0?运行结果My name is snoopyMy name is 解决办法:深拷贝构造函数CDog:CDog(const CDog& dog)name=new charstrlen()+1;strcpy(name,);深拷贝的内存分配void fun(CDog dog) ; /什么也不做void main()CDog dog1 (“snoopy”);dog1.print_name();fun(dog1);dog1.print_name();

34、dognamedog1namesnoopysnoopy4、复杂情况:动态构造小狗void main()CDog *pDog=new CDog(“snoopy”);dog1-print_name();name栈pDogsnoopy0堆动态数组?CDog *pDog=new CDog3; 堆栈pDogsnoopy0haba0 xxx0 namenamename迷失的指针!void fun() CDog *pDog=new CDog3; return;堆栈pDogsnoopy0haba0 xxx0 namenamename内存泄漏!使用数组?CDog dogs3=“snoopy”, “haba”,

35、xxx”;堆栈dogs0dogsdogs1dogs2namenamenamesnoopy0haba0 xxx0 可靠的数组!void fun() CDog dogs3=“snoopy”, “haba”, xxx”;return;堆栈dogs0dogsdogs1dogs2namenamenamesnoopy0haba0 xxx0 5、隐含的this指针每个类中都隐含的this指针成员,不用定义;对于所定义的每个对象,this指向当前对象的地址;通过对象调用成员函数时,隐含都要传递this指针作为实参;this指针是常量指针,不能再指向别的对象;在成员函数中访问成员数据或其它成员函数,可以通过th

36、is-进行限定,但通常可以省略。this的使用class CDogprivate:int age;public:CDog() age=1; void AddAge() this-age+; void show() cout“Im ” age“ year old.”限定符可有可无谁在调用show问题?void main()CDog dog1,dog2;dog1.AddAge();dog1.show();dog2.show();dog11dog21show2深入理解this普通成员函数隐含的this dog1.show();dog1.show(this);show(CDog *)&dog1);do

37、g12showthis应避免的this用法class CDogprivate:int age;public:CDog() age=1; void SetAge(int age) this-age = age; void show() cout“Im ” age“ year old.”endl; ;this限定的age是成员,age是参数。主要内容3.2 类和对象3.3 构造函数和析构函数3.4 对象数组、指针、引用3.5 静态成员3.1 面向对象概述3.6 友元3.7 对象成员1、静态数据成员定义及初始化class CDogprivate:int age;static int counter;

38、int CDog:counter=0; 定义并初始化声明2、静态数据成员的特点静态数据成员在内存中只有一份,不管内存中是否存在对象或者存在多少个对象,静态数据成员只有一份。公有静态成员:可以在成员函数中随意访问,也可以通过类名称访问;私有静态成员:不能通过类名访问,但可以借助对象调用公有成员函数间接访问。记录小狗的条数class CDogpublic:static int counter;CDog() counter+; CDog() counter-; ;int CDog:counter=0; 初始时没有小狗对象记录小狗的条数void main()CDog dog1;coutdog1.cou

39、nterendl;CDog *dog2= new CDog();coutcounterendl;delete dog2;coutCDog:counterendl;运行结果1213、私有静态成员class CDogprivate:static int counter;public:int GetCount() return counter; ;int CDog:counter=0; /初始化通过对象的公有接口访问访问私有静态成员void main()CDog dog1;coutdog1.GetCount()endl;CDog *dog2=new CDog();coutGetCount()endl

40、;delete dog2;/coutCDog:counterz=x+y;CAdd a(10,20);a.sum(&a);/ CAdd:sum(&a);只能直接访问静态的数据成员x和y主要内容3.2 类和对象3.3 构造函数和析构函数3.4 对象数组、指针、引用3.5 静态成员3.1 面向对象概述3.6 友元3.7 对象成员1、为什么使用友元?通过私有类型,实现了封装与隐藏,提高了软件的可靠性、可重用性和可维护性,但牺牲了性能。因为增加了函数调用带来的系统开销。友元是出于执行效率的考虑,允许类外部的函数或其它的类直接访问本类的私有成员,称为友元函数或友元类。友元打破了封装和数据隐藏,除非一些特殊

41、场合,应该慎用。计算两点距离:普通函数版本class CPointint x,y;public:CPoint(int xx=0,int yy=0) x=xx; y=yy; int GetX() return x; int GetY() return y; ;计算两点距离:普通函数版本double GetDis(CPoint &a, CPoint &b)int dx,dy;dx= b.GetX()-a.GetX();dy=b.GetY()-a.GetY();return sqrt(dx*dx+dy*dy);void main()CPoint p1(1,2),p2(4,6);cout“distan

42、ce: “GetDis(p1,p2) endl;运行结果distance:5不能直接访问b.x等计算两点距离:友元函数版本class CPointint x,y;public:CPoint(int xx=0,int yy=0) x=xx; y=yy; int GetX() return x; int GetY() return y; friend double GetDis(CPoint &a,CPoint &b);声明GetDis是CPoint的友元函数计算两点距离:友元函数版本double GetDis(CPoint &a, CPoint &b)int dx,dy;dx=b.x-a.x;d

43、y=b.y-a.y;return sqrt(dx*dx+dy*dy);void main()CPoint p1(1,2),p2(4,6);cout“distance: “GetDis(p1,p2); endl;友元函数中可以通过对象访问私有成员友元函数说明友元函数不是类的成员函数,只是类之外的一个普通函数。一旦普通函数被声明为某个类的友元函数,在函数体内便可以通过对象访问类的私有成员,而不是直接访问成员。不能在函数名前加CPoint:前缀。double CPoint:GetDis(CPoint &a, CPoint &b)int dx,dy;dx=b.x-x;dy=b.y-y;return s

44、qrt(dx*dx+dy*dy);XX计算两点距离:成员函数版本class CPointint x,y;public:CPoint(int xx=0,int yy=0) x=xx; y=yy; int GetX() return x; int GetY() return y; double GetDis(CPoint &a);声明类的成员函数计算两点距离:成员函数版本double CPoint:GetDis(CPoint &a)int dx,dy;dx=x-a.x;dy=y-a.y;return sqrt(dx*dx+dy*dy);void main()CPoint p1(1,2),p2(4,

45、6);cout“distance: “ p1.GetDis(p2); endl;成员函数内部可以访问私有成员成员函数&友元函数尽量使用成员函数的方法,有时可使用友元函数。但需要注意用法上的区别,成员函数隐含this指针,在计算距离时,只需传递另外一个点对象即可。而友元函数,必须传递两个点对象进行计算。CPoint p1(1,2),p2(4,6);友元函数版本:GetDis(p1,p2);成员函数版本:p1.GetDis(p2);2、友元类C+允许将整个类说明为另一个类的友元,称为友元类,友元类中的每一个成员函数均可以通过对象访问另一个类的私有成员。友元关系不能传递,B类是A类的友元,C类是B类

46、的友元,不能推导出C类是A类的友元。友元关系是单向的,B类是A类的友元,并不表示A类是B类的友元。友元类示例class A private: int x;public: int GetX() return x; void Display() coutxendl; ;友元类:未声明友元时class B int y;public: void Set(A a); void B:Set(A a)y=a.GetX(); / 直接用a.x非法声明友元类class A friend class B;class B int y;public: void Set(A a) y=a.x; /无须a.GetX()

47、声明B是A的友元主要内容3.2 类和对象3.3 构造函数和析构函数3.4 对象数组、指针、引用3.5 静态成员3.1 面向对象概述3.6 友元3.7 对象成员对象成员当一个类的对象作为另一个类的成员时,称该对象为对象成员,这种方法称为“组合技术”。包含对象作为数据成员的类称为容器类,当创建容器类对象时,对象成员的初始化由构造函数的初始化列表提供。点类的定义class CPoint int x,y;public: int GetX() return x; int GetY() return y; CPoint(int xx=0,int yy=0) x=xx; y=yy; ;三角形类定义class

48、 CPoint ;class CTrianglepublic: CPoint p1,p2,p3; CTriangle(int,int,int,int,int,int); double GetArea();三角形类实现CTriangle:CTriangle(int x1,int y1,int x2, int y2,int x3,int y3) : p1(x1,y1), p3(x3,y3),p2(x2,y2) double CTriangle:GetArea()double s1,s2,s3,s,area;s1=sqrt(p1.GetX()-p2.GetX()*(p1.GetX()-p2.GetX()+); return area;三角形类实现void main()CTriangle a(1,2,3,5,3,7);couta.p1.GetX()endl;couta.p2.GetY()endl;couta.GetArea()endl;运行结果152构造与析构过程定义容器类对象时,如CTriangle a,先通过初始化列表调用对象成员的

温馨提示

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

评论

0/150

提交评论