For example, consider keeping track of the number of Car objects that currently exist. Since it would be quite cumbersome if every single Car object had to correctly maintain the current number of Car objects, it is better to store this value in a global variable, that is, as a static data member of the Car class. Since external users might want to find out how many Car objects exist, there should be a public: static member function to get that number. But since it would be improper for anyone but the Car class to change the value of this variable, there should not be a public: static member function to set the number of Car objects. The following class illustrates the static data member and the public: static access member function. #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
Note that static data members must be defined in a source file. It is a common C++ error to forget to define a static data member, and the symptoms are generally an error message at link time. For example, static data member Car::num_ might be defined in the file associated with class Car, such as file Car.cpp. Unlike normal data members, it is possible to access static data members before the first object of the class is created. For example, it is possible to access static data member Car::num_ before the first Car object is created, as illustrated in the main() routine that follows: 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"; } The output of this main() routine is: Before creating any cars, num() returns 0 After creating three cars, num() returns 3 It is also possible to use user-defined classes to define static data members. For example, if there were some sort of registry of Car objects and if the registry were conceptually a global variable, it would be better to define the registry as a static data member of the Car class. This is done just like the static int data member shown: just replace the type int with the type of the registry, and replace the initializer "= 0;" with whatever is appropriate as the initializer for the class of the registry. |