C++程序设计课件:第15章 静态成员与友元

上传人:鲁** 文档编号:570163152 上传时间:2024-08-02 格式:PPT 页数:41 大小:495.50KB
返回 下载 相关 举报
C++程序设计课件:第15章 静态成员与友元_第1页
第1页 / 共41页
C++程序设计课件:第15章 静态成员与友元_第2页
第2页 / 共41页
C++程序设计课件:第15章 静态成员与友元_第3页
第3页 / 共41页
C++程序设计课件:第15章 静态成员与友元_第4页
第4页 / 共41页
C++程序设计课件:第15章 静态成员与友元_第5页
第5页 / 共41页
点击查看更多>>
资源描述

《C++程序设计课件:第15章 静态成员与友元》由会员分享,可在线阅读,更多相关《C++程序设计课件:第15章 静态成员与友元(41页珍藏版)》请在金锄头文库上搜索。

1、 第15章 静态成员与友元2本章主要内容o 15.1 静态成员的需要性o 15.2 静态成员的使用o 15.3 静态数据成员o 15.4 静态成员函数o 15.5 需要友员的原因o 15.6 友员的使用 o 作业3o如果类的某些属性希望他的所有对象共享,怎么办?o数据共享途径: n途径一:全局变量或全局对象p具有局限性p破坏程序模块结构p属于程序,而不属于类n途径二:静态成员p被该类的所有对象共享15.1 静态成员的需要性415.1 静态成员的需要性o目的:类的所有对象共享某些资源 class Student / ; int count; /学生人数 Student * pFirst; /学生

2、类链表首指针 void fn( ) Student ss; /创建第一个学生对象 count+; /学生人数增1 pFirst=&ss; /没有对pFirst约束,随便乱用,完全没把它当链首指针 /fn( )退出时,ss作用域中止并被析构 ,可学生人数忘了减1 515.2 静态成员的使用o静态成员是类中的成员,是类的一部分,在类外不可任意访问,从而起到保护作用。o静态成员有静态数据成员和静态成员函数之分。o声明格式:static 成员声明;o静态数据成员与静态变量相似,具有静态生存期,是在类中声明的全局数据成员,能被同一个类的所有对象所共享。o公有静态成员函数不仅可以通过类对象来访问,还可通过

3、“类名:静态成员函数”的形式在程序中直接调用。615.2 静态成员的使用/ ch15_1.cpp1.#include 2.#include 3.class Student4. protected:5. static int noOfStudents; 6. char name40; 7. public:8. Student(char* pName =no name) 9. cout create one studentn;10. strncpy(name, pName,40);11. name39=0;12. noOfStudents +; 13. /静态成员:每创建一个对象,学生人数增114

4、. cout noOfStudents endl;15. 16. static int number( ) /静态成员函数17. return noOfStudents; 18. Student( )19. cout destruct one studentn;20. noOfStudents-; 21. /每析构一个对象,学生人数减122. cout noOfStudents endl;23. 24.;25. int Student:noOfStudents =0; 26. /静态数据成员在类外分配空间和初始化27. void fn( )28. Student s1;29. Student

5、s2;30. cout Student:number( ) endl; 31. /调用静态成员函数用类名引导32. 33. int main( )34. fn( );35. cout Student:number( ) endl; 36. /调用静态成员函数用类名引导37. 运行结果: creat one student 1creat one student22 destruct one student1destruct one student00715.2 静态成员的使用o静态数据成员不是某一个对象的一部分,而是所有对象共享它,并且能够访问它。o静态数据成员要在程序一开始运行时就必须存在。因

6、为函数在程序运行中被调用,所以静态数据成员不能在任何函数内分配空间和初始化。 o这样,静态数据成员的空间分配有三个可能的地方:(1)作为类的外部接口的头文件,那里有类声明;(2)类定义的内部实现,那里有类的成员函数定义;(3)应用程序的main( )函数前的全局数据声明和定义处。 815.2 静态成员的使用例如,下面的代码重用Student类,但在应用程序中不得不再定义Student类的静态数据成员: /student.h 类定义class Student protected: static int noOfStudents; /静态数据成员声明 char name40; public: St

7、udent(char* pName =no name); Student( ); static int number( ); /静态成员函数声明 ;915.2 静态成员的使用/student.cpp类的内部实现#include #include #include student.hStudent:Student(char* pName) cout create one studentn; strncpy(name, pName, 40); name39 = 0; noOfStudents+; cout noOfStudents endl; Student:Student( ) cout des

8、truct one studentn; noOfStudents-; cout noOfStudents endl; int Student:number( ) /静态成员函数 return noOfStudents; 1015.2 静态成员的使用file2.cpp /应用程序重用了Student类#include “student.h”#include int Student:noOfStudents=0; /初始化静态成员,不便于重用void fn( ) Student s1; Student s2; coutStudent:number( )endl;int main( ) fn( );

9、 coutStudent:number( )endl; return 0; 1115.2 静态成员的使用o静态数据成员是类的一部分,静态数据成员的定义是类定义的一部分,故可将其放在类的内部实现部分中定义。定义时,要用类名引导。重用该类时,简单地包含其头文件即可。o 例如,下面的程序将ch15_1.cpp改成了多文件程序实现结构: / student.h class Student protected: static int noOfStudents; /静态数据成员声明 char name40; public: Student(char* pName =no name); Student( )

10、; static int number( ); /静态成员函数声明 ;1215.2 静态成员的使用/student.cpp类的内部实现#include #include #include “student.h”int Student:noOfStudents = 0;Student:Student(char* pName) cout create one studentn; strncpy(name, pName, 40); name39 = 0; noOfStudents+; cout noOfStudents endl; Student:Student( ) cout destruct o

11、ne studentn; noOfStudents-; cout noOfStudents endl; int Student:number( ) return noOfStudents; 1315.2 静态成员的使用/ch15_2.cpp #include student.h /重用Student类 #include void fn( ) Student s1; Student s2; cout Student:number() endl; int main() fn( ); cout Student:number() endl; return 0; 工程文件ch15_2.prg包含: st

12、udent.cppch15_2.cpp1415.3 静态数据成员o使用静态数据成员可以节省内存,因为它只存储一处,供所有对象共享。静态数据成员的值是可修改的,但它对每个对象都是一样的。1. 定义和使用o与静态变量相似,静态数据成员是静态存储(static)的,它必须按下列两个步骤进行:n在类中使用关键字static声明静态数据成员。 n在类外为静态数据成员分配内存空间并初始化。 o其定义格式如下::=15【例】静态数据成员的使用示例1.#include 2.using namespace std;3.class CSum4.5. public:6.CSum(int a = 0, int b =

13、 0) /A7. nSum += a+b; 8.int getSum() 9. return nSum; 10.void setSum(int sum)11. nSum = sum; 12. private:13.static int nSum;14.;15.int CSum:nSum = 0;16.int main()17.18.CSum one(10, 2), two;19.coutone:sumone.getSum()endl;20.couttwo:sum=two.getSum()endl;21.two.setSum(5);22.coutone:sum=one.getSum()endl;

14、23.couttwo:sum=two.getSum()endl;24.return 0;25.运行结果:运行结果:one:sum=12two:sum=12one:sum= 5two:sum=51615.3 静态数据成员2. 几点说明o(1)静态数据成员是类中的成员,它的访问属性同普通数据成员一样,可以为public、private和protected。o(2)静态数据成员的实际定义和初始化本身是不受public、private和protected等访问属性限制的。o(3)静态数据成员可看成是类中声明、类外定义的静态全局变量,具有静态生存期,在程序中从实际定义时开始产生,到程序结束时消失。 o(

15、4)当静态数据成员为public时,在类外对该成员的访问和引用可通过对象,也可直接引用。:1715.3 静态数据成员o例:class CSum /public:static int nSum;int CSum:nSum=0;int main()CSum one;one.nSum=10;CSum:nSum=12; /常用方式coutone.nSumendl;return 0;1815.3 静态数据成员o例: class Student public: Student( ) noOfStudent+; / static int noOfStudent; /公共静态数据成员 / ; void fn(

16、Student& s1,Student& s2) couts1.noOfStudents; cout Student:noOfStudents; /此处也可以访问静态数据成员 193. 静态数据成员的使用场合:o(1) 用来保存流动变化的对象个数;o(2) 存储链表的第一个或者最后一个成员的内存地址 一个指针;o(3) 作为一个标记,标记一些动作是否发生;15.3 静态数据成员2315.4 静态成员函数o静态成员函数:在类的定义体中,前面被冠以“static”的成员函数。o静态成员函数和静态数据成员一样,都属于类的静态成员,但它们都不专属于某个对象,而是所有对象所共享的成员。o因此,访问静态成

17、员函数时,也不需要对象。n:o在类中,静态数据成员可以被成员函数或静态成员函数所引用。但反过来,静态成员函数却不能直接引用类中说明的非静态成员。 Page 232415.4 静态成员函数Page 24o例如,下面的程序,两种调用静态成员函数的方法都是合法的,且意义一样: #include class Student public: static int number( ) return noOfStudents; /. protected: char name40; static int noOfStudents; ; int Student:noOfStudents = 1; int mai

18、n( ) Student s; cout s.number() endl; /ok 用对象引用静态成员函数 cout Student:number() endl; /ok 用类名引导静态成员函数 2515.4 静态成员函数o一个静态成员函数不与任何对象相联系,故不能对非静态成员进行默认访问。o例: #include class Student public: static char* sName()/静态成员函数为所有对象共享 coutnoOfStudentsendl; return name; /error哪个对象? protected: char name40; static int no

19、OfStudents; ;26 int Student:noOfStudents=0; void fn( ) /- Student s; couts.sName( )endl; /sName( )从对象s上得到的是Student类型 /故可写成:Student : sName( ) 15.4 静态成员函数2715.4 静态成员函数(选讲)o静态成员函数借助静态数据成员头指针可以对非静态成员访问。o例ch15-6.cpp说明了一个访问对象中成员的方法: #include #include class Student public: Student(char* pName); Student( )

20、; static Student* findname(char* pName); protected: static Student* pFirst; Student* pNext; char name40; ;Page 2728 Student* Student:pFirst = 0; /静态成员空间分配及初始化 Student:Student(char*pName)/头插法 strncpy(name,pName, sizeof(name); namesizeof(name)-1=0; pNext=pFirst; pFirst=this; Student:Student( ) if(pFir

21、st=this)pFirst=pNext; return; for(Student* pS=pFirst; pS; pS=pS-pNext) if(pS-pNext=this) pS-pNext=pNext; return; /查找被析构的节点 Page 2815.4 静态成员函数2915.4 静态成员函数Student* Student:findname(char* pName)/静态成员函数 for(Student* pS=pFirst; pS; pS=pS-pNext) if(strcmp(pS-name,pName)=0) return pS; return (Student*)0;i

22、nt main( ) Student s1(Randy); Student s2(Jenny); Student s3(Kinsey); Student* pS =Student:findname(Jenny) if(pS) cout ok. endl; else cout no find. endl; return 0;3015.5 需要友元的原因o问题的提出:n对象的保护和私有成员:只允许本类的成员函数访问 n为了提高效率,希望本类以外的对象或函数能够访问类中的保护和私有成员 o友元:提供了本类外的对象访问保护和私有成员的途径。Page 3031o友元:一个类的友元可以访问这个类的保护和私

23、有成员(公有成员当然能够访问,但是一般不要改变其值。)o友元可以是下列之一: (1)友元函数不属于任何类的一般函数 (2)友元成员函数另一个类的某个成员函数 (3)友元类另一个类(整个类作友元)o注意:友元使得类的封装性受到影响,程序的可维护性变差,应慎重使用 Page 3115.5 需要友元的原因3215.6 友元的使用o友元的声明和定义n友元声明:友元声明的位置可在类的任何部位,既可在public区,也可在protected区,意义完全一 样。n友元的定义:友元不属于本类的成员,所以友元的定义不能在本类的定义体中。 1. 友元函数o友元函数:不属于任何类的、被声明为某个类的友元的一般函数。

24、o友元函数定义在类的外部,一般与类的成员函数定义放在一起。o格式:nfriend (形参表)(形参表) #includeclass A protected: int x,y; public: int z; A(int xx=0,int yy=0,int zz=0):x(xx),y(yy),z(zz) friend void in(A); friend void sh(A); ;void in(A a1) couta1.xa1.ya1.z; couta1.x a1.y a1.zendl; void sh(A a2) couta2.x a2.y a2.zendl; int main() A a1(

25、11,22,33); sh(a1); in(a1); sh(a1); return 0;3415.6友元的使用2.友元成员函数o友元成员函数:其他某个类的成员函数,是本类的友元o格式: friend 函数返回类型 类名标识符:函数名(参数列表);o说明:n友元成员函数的声明,除了前面冠以“friend”外,还要注明所属类的类名。n友元成员函数应该在自己所属类的定义体中进行定义。3515.6友元的使用class Student; /前项声明,类名声明class Teacher /- public: void assignGrades(Student& s); /给定成绩 protected: i

26、nt noOfStudents; Student * pList100; ; class Student public: /- friend void Teacher:assignGrades (Student&s); /是学生类的友元成员函数,同时又是教师类的成员函数 Page 353615.6友元的使用 protected: Teacher * pT; int semesterHours; float gpa; ; void Teacher:assignGrades(Student& s) s.gpa=4.0; /修改学生的平均成绩gpa o解决交叉声明的方法是:先进行类名声明。o类名声明

27、不能用于定义该类的对象,因为这时还没有类的完整定义,没有分配类对象空间的依据。3715.6 友元的使用3.友元类o友元类:是一个类,同时又是另一个类的友元。o友元类的说明:friend class 类名;o类A和B,B被声明为A的友元类,则B类的所有成员函数都可以访问A类的保护或私有成员。o例如,下面的代码将整个教师类看成是学生类的友类,教师既可修改成绩,又可调整学时数:Page 373815.6 友元的使用 class Student; class Teacher public: void assignGrades(Student& s); /赋成绩 void adjustHours(Stu

28、dent& s); /调整学时数 /- protected: int noOfStudents; Student * pList100; ; class Student public: friend class Teacher; /友元类 /- protected: int semesterHours; float gpa; ; Page 383915.6 友元的使用#include#includeclass A private: int x,y; public: A(int xx=0,int yy=0):x(xx),y(yy) friend class B; /友元类;class B private: char n20; public: B(char nn ) strcpy(n , nn); void sh(A a1) coutn: a1.x a1.yendl; void sum(A a1) coutn: a1.x+a1.yendl; ;4015.6 友元的使用int main() A a1(111,222); B b1(abcdefg); b1.sh(a1); b1.sum(a1); return 0; 执行结果: abcdefg: 111 222 abcdefg: 33341 作业15.1,15.2

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

最新文档


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

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