Static member variables are variables which do not belong to any objects of the class, instead shared by all the objects. Similarly to static local variables, static member variables are available throughout the program and destroyed at the program end.
We can create static member variables as shown below:
#include <iostream>
class Counter
{
public:
static int count; // only declaration. definition and initialiation outside.
};
int Counter::count{0}; // initialization must be outside.
int main(int argc, char const *argv[])
{
std::cout << Counter::count << "\n";
Counter c{};
std::cout << c.count << "\n";
return 0;
}We can access static variables on the class using scope resolution (::) and on the class object as shown above.
One thing to note that we can only declare the static variables inside the class but have to define them outside as we do with global variables.
Tip
Essentially, static member variables are global variables defined inside a namespace with one difference is that classes have access controls and namespace does not.
Defining and initializing of static member is not subject to access control, so it doesn’t matter if they are private or protected, we can defined them outside.
class Counter
{
private:
static int count;
};
int Counter::count{0}; // still works.Static member variables with multi files
If,
- Class is defined in header file, define the static member in corresponding source file. Class definition would just contain the declaration of it.
- Class is defined in header file and we want to put static member definition also in header file, we can use make the definition inline using
inlinekeyword.
Static member variables with class templates
If using class templates, static member variables definitions are typically placed immediately beneath the class definition. Including header files in multiple files would not violate ODR as definitions are implicitly inline.
Initialization of static member inside the class
As we saw above the declaration and initialization/definition are at different places. But for constant integral types (including char, and bool), const enums, the static member can be initialized in the class. For example,
class Counter
{
public:
static const int count{0}; // works
};It is also allowed for inline variables for C++17 and above. For example,
class Counter
{
public:
static inline int count{0}; // works
};This is the most common way to initialize static members.
As constexpr members are implicitly inline, they can also be initialized without using inline keyword.
class Counter
{
public:
static constexpr int count{0}; // works
};auto and CTAD allowed for static members
Static members can use auto or CTAD to deduce the type from the initializer that non-static members can’t do. For example,
class Someclass
{
public:
auto value{1}; // fails
static inline auto othervalue{1}; // works
static inline std::pair p{1, 2}; // works.
}