The program of Figs. 9.27–9.29 demonstrates a private static
data member called count
(Fig. 9.27, line 24) and a public static
member function called getCount
(Fig. 9.27, line 18). In Fig. 9.28, line 8 defines and initializes the data member count
to zero at global namespace scope and lines 12–15 define 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.28, count
is referenced by both line 22 in the constructor and line 32 in the destructor.
1 // Fig. 9.27: Employee.h
2 // Employee class definition with a static data member to
3 // track the number of Employee objects in memory
4 #ifndef EMPLOYEE_H
5 #define EMPLOYEE_H
6
7 #include <string>
8
9 class Employee
10 {
11 public:
12 Employee( const std::string &, const std::string & ); // constructor
13 ~Employee(); // destructor
14 std::string getFirstName() const; // return first name
15 std::string getLastName() const; // return last name
16
17 // static member function
18 static unsigned int getCount(); // return # of objects instantiated
19 private:
20 std::string firstName;
21 std::string lastName;
22
23 // static data
24 static unsigned int count; // number of objects instantiated
25 }; // end class Employee
26
27 #endif
1 // Fig. 9.28: Employee.cpp
2 // Employee class member-function definitions.
3 #include <iostream>
4 #include "Employee.h" // Employee class definition
5 using namespace std;
6
7 // define and initialize static data member at global namespace scope
8 unsigned int Employee::count = 0; // cannot include keyword static
9
10 // define static member function that returns number of
11 // Employee objects instantiated (declared static in Employee.h)
12 unsigned int Employee::getCount()
13 {
14 return count;
15 } // end static function getCount
16
17 // constructor initializes non-static data members and
18 // increments static data member count
19 Employee::Employee( const string &first, const string &last )
20 : firstName( first ), lastName( last )
21 {
22 ++count; // increment static count of employees
23 cout << "Employee constructor for " << firstName
24 << ' ' << lastName << " called." << endl;
25 } // end Employee constructor
26
27 // destructor deallocates dynamically allocated memory
28 Employee::~Employee()
29 {
30 cout << "~Employee() called for " << firstName
31 << ' ' << lastName << endl;
32 --count; // decrement static count of employees
33 } // end ~Employee destructor
34
35 // return first name of employee
36 string Employee::getFirstName() const
37 {
38 return firstName; // return copy of first name
39 } // end function getFirstName
40
41 // return last name of employee
42 string Employee::getLastName() const
43 {
44 return lastName; // return copy of last name
45 } // end function getLastName
1 // Fig. 9.29: fig09_29.cpp
2 // static data member tracking the number of objects of a class.
3 #include <iostream>
4 #include "Employee.h" // Employee class definition
5 using namespace std;
6
7 int main()
8 {
9 // no objects exist; use class name and binary scope resolution
10 // operator to access static member function getCount
11 cout << "Number of employees before instantiation of any objects is "
12 << Employee::getCount() << endl; // use class name
13
14 // the following scope creates and destroys
15 // Employee objects before main terminates
16 {
17 Employee e1( "Susan", "Baker" );
18 Employee e2( "Robert", "Jones" );
19
20 // two objects exist; call static member function getCount again
21 // using the class name and the scope resolution operator
22 cout << "Number of employees after objects are instantiated is "
23 << Employee::getCount();
24
25 cout << "
Employee 1: "
26 << e1.getFirstName() << " " << e1.getLastName()
27 << "
Employee 2: "
28 << e2.getFirstName() << " " << e2.getLastName() << "
";
29 } // end nested scope in main
30
31 // no objects exist, so call static member function getCount again
32 // using the class name and the scope resolution operator
33 cout << "
Number of employees after objects are deleted is "
34 << Employee::getCount() << endl;
35 } // end main
Number of employees before instantiation of any objects is 0
Employee constructor for Susan Baker called.
Employee constructor for Robert Jones called.
Number of employees after objects are instantiated is 2
Employee 1: Susan Baker
Employee 2: Robert Jones
~Employee() called for Robert Jones
~Employee() called for Susan Baker
Number of employees after objects are deleted is 0
Figure 9.29 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 12), after two Employee
objects have been created (line 23) and after those Employee
objects have been destroyed (line 34). Lines 16–29 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 lines 17–18 inside the nested scope. As each constructor executes, it increments class Employee
’s static
data member count
. These Employee
objects are destroyed when the program reaches line 29. 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.
Common Programming Error 9.6
Using the this pointer in a static member function is a compilation error.
Common Programming Error 9.7
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.