Skillversitas

Static Members in C++

Static members in C++ are data members or member functions that belong to the class itself, not to a particular object. Static data shares a single value across all objects of the same class. Static functions can be called without creating an object first.

Static members are useful for storing class-level data such as counters, shared configuration, or a single instance (singleton pattern). Static data must be defined outside the class in addition to being declared.

Code Example

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Employee {
private:
    string name;
    string department;
    int id;
    static int nextId;
    static int totalEmployees;

public:
    Employee(string empName, string dept) : name(empName), department(dept) {
        id = nextId++;
        totalEmployees++;
        cout << "Employee \"" << name << "\" added (ID: " << id << ")" << endl;
    }

    ~Employee() {
        totalEmployees--;
        cout << "Employee \"" << name << "\" removed" << endl;
    }

    void displayInfo() {
        cout << "ID: " << id << ", Name: " << name << ", Dept: " << department << endl;
    }

    int getId() const {
        return id;
    }

    static int getTotalEmployees() {
        return totalEmployees;
    }

    static int getNextId() {
        return nextId;
    }
};

int Employee::nextId = 1001;
int Employee::totalEmployees = 0;

class AppConfig {
private:
    static AppConfig* instance;
    string appName;
    int maxUsers;
    bool debugMode;

    AppConfig() : appName("SkillVersitas"), maxUsers(1000), debugMode(false) {
        cout << "AppConfig initialized" << endl;
    }

public:
    static AppConfig* getInstance() {
        if (instance == nullptr) {
            instance = new AppConfig();
        }
        return instance;
    }

    string getAppName() const { return appName; }
    int getMaxUsers() const { return maxUsers; }
    bool isDebugMode() const { return debugMode; }

    void setDebugMode(bool mode) { debugMode = mode; }
    void setMaxUsers(int max) { maxUsers = max; }

    void displayConfig() {
        cout << "App: " << appName << ", Max Users: " << maxUsers
             << ", Debug: " << (debugMode ? "ON" : "OFF") << endl;
    }
};

AppConfig* AppConfig::instance = nullptr;

class MathUtils {
public:
    static double square(double x) {
        return x * x;
    }

    static double cube(double x) {
        return x * x * x;
    }

    static int max(int a, int b) {
        return (a > b) ? a : b;
    }

    static int min(int a, int b) {
        return (a < b) ? a : b;
    }
};

int main() {
    cout << "=== Static Data Members ===" << endl;
    cout << "Total employees: " << Employee::getTotalEmployees() << endl;

    Employee emp1("Peter", "Engineering");
    Employee emp2("John", "Marketing");
    Employee emp3("Sarah", "Design");

    cout << "\nTotal employees: " << Employee::getTotalEmployees() << endl;

    emp1.displayInfo();
    emp2.displayInfo();
    emp3.displayInfo();

    cout << "\nNext ID: " << Employee::getNextId() << endl;

    cout << "\n=== Singleton Pattern ===" << endl;
    AppConfig* config1 = AppConfig::getInstance();
    config1->displayConfig();

    AppConfig* config2 = AppConfig::getInstance();
    config2->setDebugMode(true);
    config2->setMaxUsers(5000);

    cout << "config1 == config2: " << (config1 == config2 ? "true" : "false") << endl;
    config1->displayConfig();

    cout << "\n=== Static Member Functions ===" << endl;
    cout << "Square of 5: " << MathUtils::square(5) << endl;
    cout << "Cube of 3: " << MathUtils::cube(3) << endl;
    cout << "Max(10, 20): " << MathUtils::max(10, 20) << endl;

    cout << "\n=== Destruction ===" << endl;
    delete AppConfig::getInstance();

    return 0;
}

Code Explanation

  1. static int nextId - Static data. Declared inside the class, but there is only one copy for all Employee objects.

  2. static int totalEmployees - A static counter that keeps increasing as objects are created and decreasing as objects are destroyed.

  3. int Employee::nextId = 1001 - Definition of static data outside the class. This is mandatory because static data does not belong to any object.

  4. static int getTotalEmployees() - A static function. It can be called without an object: Employee::getTotalEmployees().

  5. id = nextId++ - Each new object gets a unique ID from the static counter. All objects share the same counter.

  6. class AppConfig - The singleton pattern. The constructor is private so no objects can be created from outside.

  7. static AppConfig* getInstance() - A static function that returns the single instance. If it does not exist yet, it creates one. If it already exists, it returns the existing one.

  8. config1 == config2 - Both point to the same object because a singleton has only one instance.

  9. MathUtils::square(5) - A static utility function. There is no need to create a MathUtils object because there are no data members.

Everyday Use Cases

Imagine a traffic light. All drivers at one intersection share the same information: the total number of vehicles (a counter), the light timing settings (configuration), and the traffic rules (utilities). There is no traffic light per car, but one shared set of information for everyone. A singleton is like a single head office that manages the entire city's traffic light network.

Conclusion

Static data shares a single value across all objects of a class. Static functions can be called without an object. Static data must be defined outside the class. The singleton pattern uses a private constructor and a static function to ensure only one instance of the class exists. Use static for class-level data, counters, shared configuration, and utility functions.