第十五章 静态成员与友元
15.2 静态成员的使用;
静态数据成员在类声明外分配空间和初始化
调用静态数据成员用类名类引导
调用静态成员函数用类名来引导
静态数据成员要实际的分配空间,故不能在类声明中定义(只能声明数据成员)。类声明只声明一个类的“尺寸与规格”,并不进行实际的内存分配,所以在类的声明中写成定义“static int noOfStudents = 0”是错误的。他也不能在头文件中类声明的外部定义,因为那会造成在多个使用该类的源文件中,对其重复定义。
静态数据成员也不能在main函数之前的全局数据声明处定义,因为那样会使每个重用该类的应用程序在包含了声明该类的头文件后,都不得不在应用程序中再定义一下该类的静态成员。
静态数据成员是类的一部分,静态数据成员的定义是类定义的一部分,将其放在类的内部实现部分中定义是再合适不过了。定义时,要用类名引导。重用该类时,简单的包含该类的头文件即可。
int Student::noOfStudents = 0; //在类的内部实现中分配空间和初始化。
公共静态数据成员可以被类的外部访问,保护或私有静态数据成员只可
被类的内部访问。
在类的外部,访问静态数据成员的形式可以是s1.noOfStudents,她
等价于s2.noOfStudents,更通常的用法是Student::noOfStudent
s(不能用Student.noOfStudents)。其意义是,静态数据成员是属
于Student类的,而不是属于哪个特定对象的,她也不需要依赖某个特
定对象的数据。
15.4 静态成员函数
静态成员函数是类的内部实现,属于类定义的一部分。她的定义位置与一般成员函数一样。
与静态数据成员一样,静态成员函数与类项联系,不予类的对象相联系,所以访问静态成员函数时,不需要对象。如果用对象去引用静态成员函数,只是用其类型。
一个静态成员函数不予任何对象向联系,故不能对非静态成员进行默认访问。
例如:class Student
{
public:
static char * sName() //静态成员函数是所有对象共享的
{
cout< <
return name; //error 哪个对象的name
}
protected:
char name[40];
static int noOfStudents;
}
int Student::noOfStudents = 0;
void main()
{
Student s;
cout< <
}
然而,不是说静态成员函数不能对非静态成员函数访问。
如链表中,查找一个学生,可以通过临时指针不断指向所要用的对象,借此来访问对象成员。
静态成员函数与非静态成员函数的根本区别是 静态成员函数没有this指针,而非静态成员函数有一个指向当前对象的指针this 。
15.5 需要友元的原因:有时候,普通函数需要直接访问一个类的保护或私有数据成员。如果没有友元机制,则只能将类的数据成员声明为公共的,从而,任何函数都可以无约束的访问它。
15.6 在类里声明一个普通函数,标上关键字friend ,就成了该类的友元,可以访问该类的一切成员。
一个类的成员函数可以是另一个类的友元。
例如:下面的代码中,教师应该可以修改学生的成绩(访问学生类的保护数据),将教师类的成员函数assignGrades()声明为学生类的友元:
class Student; // 前向声明,类名声明
class Teacher
{
public:
void assignGrades(Student& s); //给定成绩
protected:
intnoOfStudents;
Student * pList[100];
};
class Student
{
friend void Teacher::assignGrades(Student & s);
protected:
Teacher * pt;
int semesterHours;
float gpa;
};
void Teacher::assignGrades(Student & s)
{
s.gpa = 4.0; // 修改学生的平均成绩gpa
}
整个类可以另一个类的友元。