The class members are by default non-static. That means we can access them in the context of an object only. Each object will have its own copy of the data members. Even though the code segment is common for all objects of a class, the member functions can be called in the context of an object only.
Let’s assume that we have a class called Student. It has two data members – student id and name. We can create an object for each student. Each object, representing a particular student, will have its own copy id and name.
But we might have some information that are not individual student specific – rather, the class specific. For example, the total number of student in a school can not be related to any specific student. It represents a property of the class. We use static members for this type of information.
Important Properties of Static Members
- Static members are not object specific. We can not access them through an object. But we can access them through the class.
- Member function can also be static. These functions can only access the static data members. But the non-static member functions can access both static and non-static data members.
- Static members get initialized even before the main() starts and remain persisted till the lifetime of the program.
- The static member functions can not access this pointer.
Program with Static Class Member
#include <iostream>
#include <string>
using namespace std;
class Student {
public:
static int student_count;
static int getTotalStudents() {
return student_count;
}
Student(int id, string name) {
id_ = id;
name_ = name;
student_count++;
}
~Student() {
student_count--;
}
string getName() {
return name_;
}
private:
int id_;
string name_;
};
int Student::student_count = 0;
int main() {
cout << "Total students: " << Student::getTotalStudents() << endl;
cout << endl << "Creating 3 students..." << endl;
Student *s1 = new Student(1, "Tom");
Student *s2 = new Student(2, "Jack");
Student *s3 = new Student(2, "Harry");
cout << "Total students: " << Student::getTotalStudents() << endl;
cout << endl << "Deleting one student..." << endl;
delete s3;
cout << "Total students: " << Student::getTotalStudents() << endl;
// clean up;
delete s1;
delete s2;
return 0;
}
$ g++ -o test test.cpp
$ ./test
Total students: 0
Creating 3 students...
Total students: 3
Deleting one student...
Total students: 2
In our example class, we have to static members – a variable and a function.
The static variable, student_count, tracks the total number of students. Every time a Student object is created, this variable is incremented by 1 from the constructor. Similarly, if an object gets destroyed, this is decremented by 1 from the destructor.
Event though this static variable is accessed and changed from the constructor and destructor, it is not part of any specific object. It is sort of global to the class. We can access it using the class.
The static member function, getTotalStudents(), simply returns the value of the static variable.
We initialized the static variable with 0 before main(). We printed the total number of students at the beginning of main(). It rightfully printed 0 as there was no object created.
Then we created three student objects. We created the objects dynamically to destroy them later easily.
We can see from the output that the getTotalStudents() returned 3 because there were total 3 student objects at that moment.
Now we deleted one student object. After that getTotalStudents() returned 2.
Notice that we used the class, Student, to call the getTotalStudents() function – not any object.
We could directly access the static variable, student_count, though. But it is generally a good idea to access data member via a member function.