static
Class MembersThere is an important exception to the rule that each object of a class has its own copy of all the data members of the class. In certain cases, only one copy of a variable should be shared by all objects of a class. A static
data member is used for these and other reasons. Such a variable represents “classwide” information, i.e., data that is shared by all instances and is not specific to any one object of the class. Recall, for example, that the GradeBook
classes in Chapter 7 use static
data members to store constants representing the number of grades that all GradeBook
objects can hold.
Let’s further motivate the need for static
classwide data with an example. Suppose that we have a video game with Martian
s and other space creatures. Each Martian
tends to be brave and willing to attack other space creatures when the Martian
is aware that at least five Martian
s are present. If fewer than five are present, each Martian
becomes cowardly. So each Martian
needs to know the martianCount
. We could endow each object of class Martian
with martianCount
as a data member. If we do, every Martian
will have a separate copy of the data member. Every time we create a new Martian
, we’ll have to update the data member martianCount
in all Martian
objects. Doing this would require every Martian
object to have, or have access to, handles to all other Martian
objects in memory. This wastes space with the redundant copies of the martianCount
and wastes time in updating the separate copies. Instead, we declare martianCount
to be static
. This makes martianCount
classwide data. Every Martian
can access martianCount
as if it were a data member of the Martian
, but only one copy of the static
variable martianCount
is maintained in the program. This saves space. We save time by having the Martian
constructor increment static
variable martianCount
and having the Martian
destructor decrement martianCount
. Because there’s only one copy, we do not have to increment or decrement separate copies of martianCount
for each Martian
object.
Use static
data members to save storage when a single copy of the data for all objects of a class will suffice—such as a constant that can be shared by all objects of the class.
static
Data MembersA class’s static
data members have class scope. A static
data member must be initialized exactly once. Fundamental-type static
data members are initialized by default to 0
. Prior to C++11, a static
const
data member of int
or enum
type could be initialized in its declaration in the class definition—all other static
const
data members had to be defined and intialized at global namespace scope (i.e., outside the body of the class definition). In C++11, all static
const
data members can have in-class initializers. If a static
data member is an object of a class that provides a default constructor, the static
data member need not be initialized because its default constructor will be called.
static
Data MembersA class’s private
(and protected
; Chapter 11) static
members are normally accessed through the class’s public
member functions or friend
s. A class’s static
members exist even when no objects of that class exist. To access a public
static
class member when no objects of the class exist, simply prefix the class name and the scope resolution operator (::
) to the name of the data member. For example, if our preceding variable martianCount
is public
, it can be accessed with the expression Martian::martianCount
, even when there are no Martian
objects. (Of course, using public
data is discouraged.)
To access a private
or protected
static
class member when no objects of the class exist, provide a public
static
member function and call the function by prefixing its name with the class name and scope resolution operator. A static
member function is a service of the class, not of a specific object of the class.
A class’s static
data members and static
member functions exist and can be used even if no objects of that class have been instantiated.
static
Data MembersThe program of Figs. 9.28–9.30 demonstrates a private
static
data member called count
(Fig. 9.28, line 23) and a public
static
member function called getCount
(Fig. 9.28, line 17). In Fig. 9.29, line 8 defines and initializes the data member count
to zero at global namespace scope and line 12 defines static
member function getCount
. Notice that neither line 8 nor line 12 includes keyword static
, yet both lines define static
class members. The static
keyword cannot be applied to a member definition that appears outside the class definition. Data member count
maintains a count of the number of objects of class Employee
that have been instantiated. When objects of class Employee
exist, member count
can be referenced through any member function of an Employee
object—in Fig. 9.29, count
is referenced by both line 18 in the constructor and line 27 in the destructor.
Figure 9.30 uses static
member function getCount
to determine the number of Employee
objects in memory at various points in the program. The program calls Employee::getCount()
before any Employee
objects have been created (line 11), after two Employee
objects have been created (line 22) and after those Employee
objects have been destroyed (line 33). Lines 15–28 in main
define a nested scope. Recall that local variables exist until the scope in which they’re defined terminates. In this example, we create two Employee
objects in the nested scope (lines 16–17). As each constructor executes, it increments class Employee
’s static
data member count
. These Employee
objects are destroyed when the program reaches line 28. At that point, each object’s destructor executes and decrements class Employee
’s static
data member count
.
A member function should be declared static
if it does not access non-static
data members or non-static
member functions of the class. Unlike non-static
member functions, a static
member function does not have a this
pointer, because static
data members and static
member functions exist independently of any objects of a class. The this
pointer must refer to a specific object of the class, and when a static
member function is called, there might not be any objects of its class in memory.
Using the this
pointer in a static
member function is a compilation error.
Declaring a static
member function const
is a compilation error. The const
qualifier indicates that a function cannot modify the contents of the object on which it operates, but static
member functions exist and operate independently of any objects of the class.