FAQ 2.22
尽管C++允许在类的外部声明全局对象,但是最好将全局对象声明为一些类的静态数据成员,在类块的protected:里声明静态数据成员,如果需要,可以用public:静态数据成员来提供get,用procteted:静态数据成员提供set。
例如:考虑当前存在的Car对象的数目,既然让每一个Car对象都去计算Car对象的数目是很繁杂的,就不如把这个值存储为全局变量,也就是说,一个静态的Car类成员,既然额外的用户可能需要得到Car对象的数目。就应当用一个公有的静态成员函数去得到数目,但是既然不是让每一个能改变这个变量的值,就应当不是一个public:静态成员函数来设置Car对象的数目,下面的演示了静态数据成员和public:静态访问成员函数。
#include <iostream> using namespace std; class Car { public: Car(); ~Car(); Car(const Car& c); static int num(); <-- 1 protected: static int num_; <-- 2 }; Car::Car() { ++num_; } Car::~Car() { --num_; } int Car::num() { return num_; } int Car::num_ = 0; <-- 3
(1) 访问num_成员函数
(2) 声明静态数据成员
(3) 定义静态数据成员
注意:静态数据成员必须被定义在源文件内如果忘了定义静态数据成员,通常会产生一个C++错误,它的特定是链接时的错误消息。例如,静态成员Car::num_可能被定义在与类Car相关的文件里,例如Car.cpp.
不象普通的数据成员,在类的第一个对象创建之前可以访问静态数据成员,例如,在第一个Car对象被创建之前可以去访问静态数据成员Car::num_,下面是main()程序的展示:
int main() { cout << "Before creating any cars, num() returns " << Car::num() << "/n"; Car a, b, c; cout << "After creating three cars, num() returns " << Car::num() << "/n"; }
用用户定义的类定义静态数据成员也是允许的,如果存在某种Car对象的注册,例如,有一些种类的Car对象注册如果注册是一个全局变量,最好将注册定义为类的静态数据成员,这类似于静态int数据成员,只需要用registry的类型替换int类型,并且替换初始化的"=0;"改用registry的初始化。