Skip to the content of the web site.

Lesson 164: Static member variables

Previous lesson Next lesson


The member variables of every instance of a class are different—changing one will not affect the others. There are some circumstances, however, where it would be useful to share a variable between all instances of a class. This is done by declaring the variable to be static:

A member variable that is declared static is shared by all instances of the class. Such a variable is often called a class variable.

One of the most common uses of a static member variable of a class is to store how many instances of the class are currently in existence. For example, the following class

Unique identifiers

The following class gives each new instance a unique identifying number. It does so by having a static member variable (or class variable) next_unique_id, which is initially set to 0. When the constructor is called, the current value becomes the unique identifier for that instance, and the variable is then incremented. Suppose we determined that there will never, under any circumstances, be a requirement for more than $2^16$ instances of this class, so we will restrict our unique ID to an unsigned short:

// Class_unique.h
#include <cstdlib>
#pragma once

// Class declaration
class Class_unique;

// Class definition
class Class_unique {
	public:
		 Class_unique();
		// Other public member functions

		unsigned short get_id();

	private:
		unsigned short unique_id;
		static unsigned short next_unique_id;
		// Other private member functions and member variables
};
// Class_unique.cpp
#include "Class_unique.h"

// Initialize the static member variable 'next_unique_id' to zero
unsigned short Class_unique::next_unique_id = 0;

Class_unique::Class_unique() {
	// Do other constructor things...
	unique_id = Class_unique::next_unique_id;
	++Class_unique::next_unique_id;
}

unsigned short Class_unique::get_id() {
	return unique_id;
}

If we execute the following program that uses this class, as expected, the instances a, b, c and d have unique identifiers equal to $0$, $1$, $2$ and $3$, respectively:

#include <iostream>
#include "Class_unique.h"

int main() {
	Class_unique a{};
	Class_unique b{};
	Class_unique c{};

	std::cout << "The unique id of 'a' is " << a.get_id() << std::endl;
	std::cout << "The unique id of 'b' is " << b.get_id() << std::endl;
	std::cout << "The unique id of 'c' is " << c.get_id() << std::endl;

	Class_unique d{};

	std::cout << "The unique id of 'd' is " << d.get_id() << std::endl;

	return 0;
}

Counting instances

The following class stores the number of instances in a static member variable (or class variable) instance_count, initially set to 0. Each time the constructor is called, this variable is incremented, and each time the destructor is called, the variable is decremented.

// Class_instances.h
#include <cstdlib>
#pragma once

// Class declaration
class Class_instances;

// Class definition
class Class_instances {
	public:
		 Class_instances();
		~Class_instances();
		// Other public member functions

	private:
		static size_t instance_count;
		// Other private member functions and member variables
};
// Class_instances.cpp
#include "Class_instances.h"

// Initialize the static member variable 'instance_count' to zero
size_t Class_instances::instance_count = 0;

Class_instances::Class_instances() {
	// Do other constructor things...
	++instance_count;
	std::cout << "There are " << instance_count
	          << " instances" << std::endl;
}

Class_instances::~Class_instances() {
	// Do other destructor things...
	--instance_count;
	std::cout << "There are now only " << instance_count
	          << " instances" << std::endl;
}

If you were to run this code on the example

#include <iostream>
#include "Class_instances.h"

int main() {
	Class_instances a{};

	{
		Class_instances b{};

		{
			Class_instances c{};
		}  // c goes out of scope; the destructor is called on it

		Class_instances d{};
	}  // b and d go out of scope; the destructor is called on each

	std::cout << "end of the block" << std::endl;

	// b goes out of scope; the destructor is called on it
	return 0;
}

Constants

Constants that are related to a class are often public static constants:

// Class_phycis.h
#pragma once

// Class declaration
class Class_physics;

// Class definition
class Class_physics {
	public:
		static double const ATOMIC_MASS_CONSTANT;         // kg
		static double const ATOMIC_MASS_CONSTANT_ERROR;   // kg
		static double const AVOGADRO_CONSTANT;            // 1/mol
		static double const AVOGADRO_CONSTANT_ERROR;      // 1/mol
		static double const BOLTZMANN_CONSTANT;           // J/K
		static double const BOLTZMANN_CONSTANT_ERROR;     // J/K
		static double const ELECTRON_MASS;                // kg
		static double const ELECTRON_MASS_ERROR;          // kg
		static double const ELEMENTARY_CHARGE;            // C
		static double const ELEMENTARY_CHARGE_ERROR;      // C
		static double const GAS_CONSTANT;                 // J/mol K
		static double const GAS_CONSTANT_ERROR;           // J/mol K
		static double const GRAVITATIONAL_CONSTANT;       // Nm^2/kg^2
		static double const GRAVITATIONAL_CONSTANT_ERROR; // Nm^2/kg^2
		static double const NEUTRON_MASS;                 // kg
		static double const NEUTRON_MASS_ERROR;           // kg
		// And many others...

		// Other public declarations

	private:
		// Private member functions and member variables
};

The constants are defined in the corresponding source file:

// Class_phycis.cpp
#include "Class_physics.h"

double const Class_physics::ATOMIC_MASS_CONSTANT         = 1.660539040e-27;
double const Class_physics::ATOMIC_MASS_CONSTANT_ERROR   = 0.000000020e-27;

double const Class_physics::AVOGADRO_CONSTANT            = 6.022140857e23;
double const Class_physics::AVOGADRO_CONSTANT_ERROR      = 0.000000074e23;

double const Class_physics::BOLTZMANN_CONSTANT           = 1.38064852e-23;
double const Class_physics::BOLTZMANN_CONSTANT_ERROR     = 0.00000079e-23;

double const Class_physics::ELECTRON_MASS                = 9.10938356e-31;
double const Class_physics::ELECTRON_MASS_ERROR          = 0.00000011e-31;

double const Class_physics::ELEMENTARY_CHARGE            = 1.6021766208e-19;
double const Class_physics::ELEMENTARY_CHARGE_ERROR      = 0.0000000098e-19;

double const Class_physics::GAS_CONSTANT                 = 8.3144598;
double const Class_physics::GAS_CONSTANT_ERROR           = 0.0000048;

double const Class_physics::GRAVITATIONAL_CONSTANT       = 6.693e-11;
double const Class_physics::GRAVITATIONAL_CONSTANT_ERROR = 0.034e-11;

double const Class_physics::NEUTRON_MASS                 = 1.674927471e-27;
double const Class_physics::NEUTRON_MASS_ERROR           = 0.000000021e-27;

All of these constants can be accessed by any functions in files that include "Class_physics.h" and the user can access these through, for example, Class_physics::GAS_CONSTANT.

Questions and practice:

1.


Previous lesson Next lesson