CppStatic Members

Static Members

Ordinary member variables exist once per object — every instance of a class has its own independent copy. A static member variable, in contrast, exists once per class: every object of that class shares the same single copy, no matter how many instances are created.

Static member variables

A static member shared by every instance

CPP
class Robot {
public:
    static int totalRobots; // declaration — one copy shared by ALL Robot objects

    Robot() {
        totalRobots++; // every new Robot increments the single shared counter
    }
};

// Definition — required outside the class in a .cpp file (pre-C++17 style).
int Robot::totalRobots = 0;

int main() {
    Robot a, b, c;
    std::cout << Robot::totalRobots << "\n"; // 3 — shared across a, b, and c
}
Note
In C++17 and later, you can define and initialize the static member directly inside the class using `inline static`, avoiding the separate out-of-class definition entirely: `inline static int totalRobots = 0;` This is simpler and is the preferred style in modern code.

C++17: inline static simplifies the definition

CPP
class Robot {
public:
    inline static int totalRobots = 0; // definition lives right here, no .cpp needed

    Robot() { totalRobots++; }
};
Static member functions

A static member function belongs to the class rather than to any particular object — it has no this pointer, so it can only access other static members (it cannot touch instance/member variables, since there is no specific object to look them up on). It is called through the class name using ::, rather than through an object with ..

Calling a static function via ClassName::

CPP
class Robot {
public:
    inline static int totalRobots = 0;

    Robot() { totalRobots++; }

    static int getTotalRobots() { // no 'this' — can only touch static members
        return totalRobots;
    }
};

int main() {
    Robot a, b;
    std::cout << Robot::getTotalRobots() << "\n"; // 2 — called via the class, not an object
}
Practical example: an instance counter

Combining a static variable with a constructor (to increment) and a destructor (to decrement) gives a live count of how many objects of a class currently exist — a common and genuinely useful pattern.

Tracking how many instances currently exist

CPP
#include <iostream>

class Connection {
public:
    inline static int activeConnections = 0;

    Connection()  { activeConnections++; }
    ~Connection() { activeConnections--; }

    static int getActiveConnections() {
        return activeConnections;
    }
};

int main() {
    std::cout << Connection::getActiveConnections() << "\n"; // 0
    {
        Connection c1;
        Connection c2;
        std::cout << Connection::getActiveConnections() << "\n"; // 2
    } // c1 and c2 destroyed here — destructors decrement the counter
    std::cout << Connection::getActiveConnections() << "\n"; // 0
}
Static vs. instance members at a glance
  • Instance member: one copy per object; accessed via object.member; can be read/modified using this inside non-static methods.

  • Static member: one copy per class, shared by all objects (and accessible even if zero objects exist); accessed via ClassName::member; has no this in static functions.

Note
Static members are a good fit for class-wide counters, shared configuration, caches, or utility functions that don't need any particular object's data (for example, a `Math::square(x)`-style helper). If a function needs an object's own state, it should be a regular (non-static) member function instead.