,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,第十四章 静态成员与友员,14.1 静态成员的需要性,14.2 静态成员的使用,14.3 静态数据成员,14.4 拷贝构造函数,14.5 需要友元的原因,14.6 友元的使用,14.1 静态成员的需要性,原因:,1有一些属性是类中所有对象共有的。,2如果放在全局变量中,那么它们在类的外面,既不平安,又影响了重用性。,3面对庞大的程序,没有真正指明哪个函数具体负责。这种无规那么会引起软件设计的混乱,一旦程序变大,维护量就急剧上升。,解决方法:静态成员。它属于类的一局部,但既不同于普通成员,也不同于全局变量。,第十四章 静态成员与友员,14.1 静态成员的需要性,14.2 静态成员的使用,14.3 静态数据成员,14.4 拷贝构造函数,14.5 需要友元的原因,14.6 友元的使用,14.2 静态成员的使用,静态成员的,分类,:静态数据成员和静态成员函数。用,static,声明。,例1:在类中定义了一个静态数据成员和一个静态成员函数,在它的构造函数和析构函数中对静态数据成员进行操作,在应用程序中,调用了静态成员函数。,/ch15_1.cpp,#include,#include,class Student,public:,Student(char*pName=“no name),cout“create one studentn;,strcpy(name,pName);,noOfStudents+;,/静态成员:每创立一个对象,学生人数增1,coutnoOfStudentsendl;,例1:续1,Student(),cout“destruct one studentn;,noOfStudents-;,/每删除一个对象,学生人数减1,coutnoOfStudentsendl;,static int number()/静态成员函数,return noOfStudents;,protected:,static int noOfStudents;,/不能写成 noOfStudents=0;,char name40;,;,例1,:续2,int Student:noOfStudents=0;,/静态数据成员在类声明外分配空间和初始化,void fn(),Student s1;,Student s2;,coutStudent:number()endl;,/调用静态成员函数用类名引导,void main(),fn(),coutStudent:number()endl;,/调用静态成员函数用类名引导,例1,:续3,结果:,create one student,1,create one student,2,2,destruct one student,1,destruct one student,0,0,14.2 静态成员的使用(续1),说明,:,1.静态成员只有一个,所有的类对象都共享它,并且能够访问它。,2.在类对象空间中,是没有静态数据成员的,它的空间,不会随着对象的产生而分配,或随着对象的消失而回收。所以它的空间分配并不在Student的构造函数里完成,并且空间回收也不在类的析构函数里完成。,3.静态数据成员在程序的一开始时就必须存在。它的空间分配是在类定义的内部实现,那里有类的成员函数定。,例2:将ch15_1.cpp改成多文件结构。,/Student.h,class Student,public:,Student(char*pName=no name);,Student();,static int number();,protected:,static int noOfStudents;,char name40;,;,例2:续1,/student.cpp,#include,#include,#include“Strdent.h,int Student:noOfStudent=0;,/在类的内部实现中分配空间和初始化,Student:Student(char*pName),cout create one studentn;,strcpy(name,pName);,noOfStudents+;,/静态成员:每创立一个对象,学生人数增一,coutnoOfStudentsendl;,例2:续2,Student:Student(),cout destruct one studentn;,noOfStudents-;,/每删除一个对象,学生人数减1,coutnoOfStudentsendl;,int Student:number()/静态成员函数,return noOfStudents;,例2:续3,/ch15_2.cpp,#include“Strdent.h,#include,void fn(),Student s1;,Sutdent s2;,coutStudent:number()endl;,void main(),fn();,coutStudent:number()endl;,/ch15_2.prj,student.cpp,ch15_2.cpp,第十四章 静态成员与友员,14.1 静态成员的需要性,14.2 静态成员的使用,14.3 静态数据成员,14.4 拷贝构造函数,14.5 需要友元的原因,14.6 友元的使用,14.3 静态数据成员,说明:,1公共静态数据成员可被类的外部访问,保护或私有静态数据成员只可被类的内部访问。,2静态数据成员是属于类的,而不是属于哪个特定对象的,不需要信赖某个特定对象的数据。,14.3 静态数据成员(续1),静态数据成员的使用范围:,1用来保存流动变化的对象个数;,2作为一个标志,指示一个特定的动作是否发生;,3一个指向一个链表第一成员或最后一个成员的指针。,例1:公共的静态数据成员的使用。,class Student,public:,Student(char*pName=“no name),noOfStudents+;/,static int noOfStudents;,/公共静态数据成员,/,;,void fn(Student s1,Sutdent s2),couts1.noOfStudentsendl;,14.3 静态数据成员(续2),说明:在类的外部访问静态数据成员的形式可以是:,1s1.noOfStudents,2s2.noOfStudents,3Student:noOfStudents,不能是:Student.noOfStudents,意义是:静态数据成员是属于类的,而不是属于哪个特定对象的,也不需要某个特定对象的数据。,例2,:描述一个学生类,该类对象是一个个的学生,它们构成一个单向链表。,/ch15_4.cpp,#include,#include,class Student,public:,Student(char*pName);,Student();,protected:,static,Student*pFirst;,Student*pNext;,char name40;,;,例2:续1,Student*Student:pFirst=0;,Student:Student(char*pName),strcpy(name,pName);,namesizeof(name)-1=0;,pNext=pFirst;,/每新建一个结点对象,就将其挂在链首,pFirst=this;,Student:Student(),coutnamepNext),if(pS-pNext=this),/找到时,pS指向当前结点的结点,pS-pNext=pNext;,/pNext即 this-pNext,return;,Student*fn(),Student*pS=new Student(“Jenny);,Student sb(“Jone);,return pS;,例2:续3,void main(),Student sa(“Jamsa);,Student*sb=fn();,Student sc(“Tracey);,Delete sb;,结果:,Jone,Jenny,Tracey,Jamsa,第十四章 静态成员与友员,14.1 静态成员的需要性,14.2 静态成员的使用,14.3 静态数据成员,14.4 拷贝构造函数,14.5 需要友元的原因,14.6 友元的使用,14.4 拷贝构造函数,说明:,1静态成员函数定义是类的内部实现,属于类定义的一局部,位置与一般成员函数一样。,2静态成员函数与类相联系,不与类的的对象相联系,所以访问静态成员函数时,不需要对象。如果用对象去引用静态成员函数,只是用其类型。,3一个静态成员函数不与任何对象联系,故不能对非静态成员进行默认访问。,4静态成员函数与非静态成员函数的根本区别:静态成员函数没有this指针,而非静态成员函数有一个指向当前对象的指针this。,例1,:两种合法的调用静态成员函数的方法。,/ch15_5.cpp,#include,class Student,public:,static,int number(),return noOfStudent;,/,protected:,char name40;,static int noOfStudent;,;,例1,:续1,int noOfStudent=1;,void main(),Student s;,cout,s.number(),endl;,/(1)用对象引用静态成员函数,cout,Student:number(),endl;,/(2)用类名引导静态成员函数,第十四章 静态成员与友员,14.1 静态成员的需要性,14.2 静态成员的使用,14.3 静态数据成员,14.4 拷贝构造函数,14.5 需要友元的原因,14.6 友元的使用,14.5 需要友元的原因,原因:普通函数需要直接访问一个类的保护或私有数据成员。如果没有友元机制,那么只能将类的数据成员声明为公共的,从而,任何函数都可以无约束地访问它。,优点:普通函数需要直接访问类的保护或私有数据成员的原因主要是为提高效率。,第十四章 静态成员与友员,14.1 静态成员的需要性,14.2 静态成员的使用,14.3 静态数据成员,14.4 拷贝构造函数,14.5 需要友元的原因,14.6 友元的使用,14.6 友元的使用,友元声明的,位置,:在类里。,友元定义的,格式,:,friend,普通函数,/成为该类的友元,可以访问该类的一切成员,14.6 友元的使用(续1),说明:,1友元函数不是成员函数,它是类的朋友,因而能够访问类的全部成员。,2在类的内部,只能声明友元函数的原型,加上friend关键字。,3友元声明的位置可在类的任何部位,可在public区或protected区,意义完全一样。,4友元函数定义在类的外部,一般与类的成员函数定义放在一起。因而类重用时,一般友元是一起提供的。,14.6 友元的使用(续2),分类:,1友元函数:一个类的成员函数可以是另一个类的友元。,2友元类:整个类可以是另一个类的友元。友元类的每个成员函数都可访问另一个类中的保护或私有数据成员。,例1,:友元函数,class Student;/前向声明,类名声明,class Teacher,/,public:void assignGrades(Student /给定成绩,protected:int noOfStudents;Student*pList100;,class Student,public:/,friend,void Teacher:assignGrades(Student,protected:,Teacher*pT;int semesterHours;float gpa;,;,void Teacher:assignGrades(Student&s),s.gpa=4.0;/修改学生的平均成绩gpa,例2,:友元类,class Student;,class Teacher,public:,void as