第6章面向对象的妥协_第1页
第6章面向对象的妥协_第2页
第6章面向对象的妥协_第3页
第6章面向对象的妥协_第4页
第6章面向对象的妥协_第5页
已阅读5页,还剩31页未读 继续免费阅读

下载本文档

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

文档简介

1、第第6章章 面向对象的妥协面向对象的妥协授课内容授课内容 6.1 封装的破坏封装的破坏友元友元 6.2 对象机制的破坏对象机制的破坏静态成员静态成员6.1 封装的破坏封装的破坏友元友元6.1 封装的破坏封装的破坏友元友元 友元可以访问与其有好友关系的类中的任友元可以访问与其有好友关系的类中的任何成员。何成员。 友元友元友元函数友元函数友元类友元类 如果在本类以外的其他地方定义了一个函如果在本类以外的其他地方定义了一个函数数(这个函数可以是不属于任何类的普通函这个函数可以是不属于任何类的普通函数,也可以是其他类的成员函数数,也可以是其他类的成员函数),在类体,在类体中用中用friend对其进行声

2、明,此函数就称为本对其进行声明,此函数就称为本类的友元函数。友元函数可以访问这个类类的友元函数。友元函数可以访问这个类中的任何成员。中的任何成员。 如何将普通函数声明为友元函数呢?看下如何将普通函数声明为友元函数呢?看下面这个简单的例子:面这个简单的例子:6.1 封装的破坏封装的破坏友元友元 6.1.1 友元友元函数函数 【例例6-1】友元普通函数。友元普通函数。 #include using namespace std; class clock /声明clock类 public: clock(int,int,int); friend void display(clock &); privat

3、e: int hour; int minute; int second; ;6.1.1 友元友元 函数函数【例例6-1】友元普通函数。友元普通函数。 #include using namespace std; class clock /声明clock类 public: clock(int,int,int); friend void display(clock &); private: int hour; int minute; int second; ;【例例6-1】友元普通函数。友元普通函数。clock:clock(int h,int m,int s) /构造函数 hour=h; minut

4、e=m; second=s; /这是友元函数,形参t是clock类对象的引用void display(clock& t) coutt.hour:t.minute:t.secondendl;int main() clock t(10,13,56); display(t); /调用display函数,实参t是clock类对象 return 0; 6.1 友元函数友元函数程序运行结果如下:程序运行结果如下:10:13:5610:13:566.1.1 友元友元 函数函数#include using namespace std;class date; /对date类的提前引用声明class clock

5、/声明clock类public: clock(int,int,int); void display(date &); private: int hour, minute, second;【例例6-2】友元成员函数。友元成员函数。class date /声明date类public: date(int,int,int); friend void clock:display(date &); private: int month; int day; int year;6.1.1 友元友元 函数函数clock:clock(int h,int m,int s) / clock类的构造函数 hour=h;

6、 minute=m; second=s; void clock:display(date &dd) coutdd.month/dd.day/dd.yearendl; couthour:minute:secondendl; date:date(int m,int d,int y) / date类的构造函数 month=m; day=d; year=y;6.1.1 友元友元 函数函数int main() clock t(10,13,56); /定义clock类对象t date d(12,25,2004); /定义date类对象d /调用t的display函数,实参是date类对象d t.displ

7、ay(d); return 0;6.1 友元函数友元函数程序运行结果如下:程序运行结果如下:12/25/200412/25/200410:13:5610:13:56 不仅可以将一个函数声明为一个类的不仅可以将一个函数声明为一个类的“朋朋友友”,而且可以将一个类,而且可以将一个类(例如例如b类类)声明为声明为另一个类另一个类(例如例如a类类)的的“朋友朋友”。这时。这时b类类就是就是a类的友元类。友元类类的友元类。友元类b中的所有成员中的所有成员函数都是函数都是a类的友元函数,可以访问类的友元函数,可以访问a类中类中的任何成员。的任何成员。6.1 封装的破坏封装的破坏友元友元 6.1.2 友元友

8、元类类class student;class teacherpublic: void assigngrades(student& s); /给出学生成绩 protected: int stu_count; /学生人数 student* plist100; /学生数组;6.1.2 友元类友元类class studentpublic: friend teacher; /友元类 protected: int num; string name; float score;6.1.2 友元类友元类 声明友元类的一般形式为:声明友元类的一般形式为: friend 类名类名; 关于友元,有三点需要说明:关于友

9、元,有三点需要说明: (1)友元函数的声明可以出现在类的任何)友元函数的声明可以出现在类的任何地方(包括在地方(包括在private和和public部分),也就部分),也就是说友元的说明不受成员访问控制符的限是说友元的说明不受成员访问控制符的限制。制。6.1.2 友元类友元类 (2)友元关系是单向的而不是双向的,如)友元关系是单向的而不是双向的,如果声明了果声明了b类是类是a类的友元类,不等于类的友元类,不等于a类类是是b类的友元类,类的友元类,a类中的成员函数不一定类中的成员函数不一定能够访问能够访问b类中的成员类中的成员 (3)友元关系是不能传递的,例如,如果)友元关系是不能传递的,例如,

10、如果b类是类是a类的友元类,类的友元类,c类是类是b类的友元类,类的友元类,并不能说并不能说c类就是类就是a类的友元类。类的友元类。6.1 对象机制的破坏对象机制的破坏静态成员静态成员 在在c+中,声明了一个类之后,可以定义该中,声明了一个类之后,可以定义该类的多个对象。系统为每个对象分配单独类的多个对象。系统为每个对象分配单独的内存空间。每一个对象都分别有自己的的内存空间。每一个对象都分别有自己的数据成员,不同对象的数据成员各自有其数据成员,不同对象的数据成员各自有其值,互不相干。但是有时我们希望有某一值,互不相干。但是有时我们希望有某一个或几个数据成员为所有对象所共有。这个或几个数据成员为

11、所有对象所共有。这样可以实现数据共享。样可以实现数据共享。6.2 对象机制的破坏对象机制的破坏 静态成员静态成员 我们知道全局变量能够实现数据共享。但是用全我们知道全局变量能够实现数据共享。但是用全局变量的安全性得不到保证,因为在各处都可以局变量的安全性得不到保证,因为在各处都可以自由地修改全局变量的值,很有可能由于某个没自由地修改全局变量的值,很有可能由于某个没注意到的失误,全局变量的值就被修改,导致程注意到的失误,全局变量的值就被修改,导致程序的失败。因此在实际工作中很少使用全局变量。序的失败。因此在实际工作中很少使用全局变量。 如果想在同类的多个对象之间实现数据共享,也如果想在同类的多个

12、对象之间实现数据共享,也不要用全局对象,可以用静态成员。静态成员包不要用全局对象,可以用静态成员。静态成员包括静态数据成员和静态成员函数。括静态数据成员和静态成员函数。6.2 对象机制的破坏对象机制的破坏 静态成员静态成员 静态数据成员是一种特殊的数据成员。它以静态数据成员是一种特殊的数据成员。它以关键字关键字static开头。例如开头。例如:6.2 对象机制的破坏对象机制的破坏 静态成员静态成员 6.2.1 静态数据成员静态数据成员class studentpublic: student(char *name=no name); static int stu_count; char name

13、40; 静态数据成员在内存中只占一份空间(而不静态数据成员在内存中只占一份空间(而不是每个对象都分别为它保留一份空间),它是每个对象都分别为它保留一份空间),它是属于类的,但它被该类的所有对象所共享,是属于类的,但它被该类的所有对象所共享,每个对象都可以访问这个静态数据成员。静每个对象都可以访问这个静态数据成员。静态数据成员的值对所有对象都是一样的。如态数据成员的值对所有对象都是一样的。如果改变它的值,则在各对象中这个数据成员果改变它的值,则在各对象中这个数据成员的值都同时改变了。这样可以节约空间,提的值都同时改变了。这样可以节约空间,提高效率。高效率。6.2.1 静态数据成员静态数据成员 说

14、明:说明: (1)如果只声明了类而未定义对象,则类的一般数)如果只声明了类而未定义对象,则类的一般数据成员是不占内存空间的,只有在定义对象时,才据成员是不占内存空间的,只有在定义对象时,才为对象的数据成员分配空间。但是静态数据成员不为对象的数据成员分配空间。但是静态数据成员不属于某一个对象,在为对象所分配的空间中不包括属于某一个对象,在为对象所分配的空间中不包括静态数据成员所占的空间。静态数据成员是在所有静态数据成员所占的空间。静态数据成员是在所有对象之外单独开辟空间。只要在类中定义了静态数对象之外单独开辟空间。只要在类中定义了静态数据成员,即使不定义对象,也为静态数据成员分配据成员,即使不定

15、义对象,也为静态数据成员分配空间,它可以被访问。在一个类中可以有一个或多空间,它可以被访问。在一个类中可以有一个或多个静态数据成员,所有的对象共享这些静态数据成个静态数据成员,所有的对象共享这些静态数据成员,都可以访问它。员,都可以访问它。6.2.1 静态数据成员静态数据成员 (2)静态数据成员不随对象的建立而分配空)静态数据成员不随对象的建立而分配空间,也不随对象的撤销而释放间,也不随对象的撤销而释放(一般数据成员一般数据成员是在对象建立时分配空间,在对象撤销时释是在对象建立时分配空间,在对象撤销时释放放)。静态数据成员是在程序编译时被分配空。静态数据成员是在程序编译时被分配空间的,到程序结

16、束时才释放空间。间的,到程序结束时才释放空间。6.2.1 静态数据成员静态数据成员 (3)静态数据成员可以初始化,但只能在类)静态数据成员可以初始化,但只能在类体外进行初始化。如:体外进行初始化。如: int student:stu_count=0; /表示对表示对student类中的静态数据成员初始化类中的静态数据成员初始化 静态数据成员可以初始化语句的一般形式为:静态数据成员可以初始化语句的一般形式为: 数据类型数据类型 类名类名:静态数据成员名静态数据成员名=初值初值; 不必在初始化语句中加不必在初始化语句中加static。6.2.1 静态数据成员静态数据成员 (4)静态数据成员既可以通

17、过对象名访问,)静态数据成员既可以通过对象名访问,也可以通过类名来访问。也可以通过类名来访问。6.2.1 静态数据成员静态数据成员 【例【例6-36-3】 访问静态数据成员访问静态数据成员。#include using namespace std;#include class studentpublic: student(char *name= no name); student(); static int stu_count; char name40;6.2.1 静态数据成员静态数据成员 【例【例6-36-3】 访问静态数据成员访问静态数据成员。#include using namespac

18、e std;#include class studentpublic: student(char *name= no name); student(); static int stu_count; char name40;student:student (char *pname) strcpy(name ,pname); stu_count+; /每创建一个对象,学生人数加1student:student () stu_count-; /每释放一个对象,学生人数减1 /对静态数据成员stu_count初始化 int student:stu_count=0; 6.2.1 静态数据成员静态数据成员

19、 int main() student s1; couts1.stu_countendl; student s2; couts2. stu_count endl; coutstudent:stu_count endl; return 0;程序运行结果如下:程序运行结果如下:1 12 21 16.2.1 静态数据成员静态数据成员 与静态数据成员不同,静态成员函数的作用与静态数据成员不同,静态成员函数的作用不是为了对象之间的沟通,而是为了能处理不是为了对象之间的沟通,而是为了能处理静态数据成员。静态数据成员。6.2 对象机制的破坏对象机制的破坏 静态成员静态成员 6.2.2 静态成员静态成员函数函

20、数【例【例6-6-4 4】 静态成员静态成员函数访问静态数据成员的例子。函数访问静态数据成员的例子。#include using namespace std;#include class student/声明student类public: student(char *name=no name); student(); static int getcount() return stu_count; private: static int stu_count; char name40;6.2.2 静态成员函数静态成员函数 student:student (char *pname) strcpy(n

21、ame ,pname); stu_count+; /每创建一个对象,学生人数加1student:student () stu_count-; /每销毁一个对象,学生人数减1int student:stu_count=0; 6.2.2 静态成员函数静态成员函数 int main() student s1; couts1.getcount()endl; student s2; couts2.getcount()endl; coutstudent:getcount()endl; return 0;6.2.2 静态成员函数静态成员函数 6.2.2 静态成员函数静态成员函数 和静态数据成员一样,静态成员

22、函数是类的一和静态数据成员一样,静态成员函数是类的一部分,而不是对象的一部分。如果要在类外调部分,而不是对象的一部分。如果要在类外调用公用的静态成员函数,可以用类名和域运算用公用的静态成员函数,可以用类名和域运算符符“:”,也允许通过对象名调用静态成员函数。,也允许通过对象名调用静态成员函数。如如: student:getcount(); / 用类名调用静态成员函用类名调用静态成员函数数 s1.getcount(); / 用对象名调用静态成员函数用对象名调用静态成员函数 但这并不意味着此函数是属于对象但这并不意味着此函数是属于对象s1的,而只的,而只是用是用s1的类型而已。的类型而已。6.2.

23、2 静态成员函数静态成员函数 说明:说明: (1)静态成员函数不能默认访问本类中的非静态成)静态成员函数不能默认访问本类中的非静态成员。当调用一个对象的成员函数(非静态成员函数)员。当调用一个对象的成员函数(非静态成员函数)时,系统会把该对象的起始地址赋给成员函数的时,系统会把该对象的起始地址赋给成员函数的this指针。而静态成员函数并不属于某一对象,它与任何指针。而静态成员函数并不属于某一对象,它与任何对象都无关,因此静态成员函数没有对象都无关,因此静态成员函数没有this指针。既然指针。既然它没有指向某一对象,就无法对一个对象中的非静态它没有指向某一对象,就无法对一个对象中的非静态成员进行默认访问成员进行默认访问(即在访问数据成员时不指定对象即在访问数据成员时不指定对象名名)。 可以说,静态成员函数与非静态成员函数的根本区别可以说,静态成员函数与非静态成员函数的根本区别是:非静态成员函数有是:非静态成员函数有this指针,而静态成员函数没指针,而静态成员函数没有有this指针,因而决定了静态成员函数不能默认访问指针,因而决定了静态成员函数不能默认访问本类中的非静态成员

温馨提示

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

评论

0/150

提交评论