C++ OOP
Static Members
Complete lesson for Static Members using LEARNCODEGURU’s 6-level learning model — from basics to advanced practice, with C++ OOP and STL where relevant.
Basics — Static Members
Section: C++ OOP. C++ static members — static variables, static member functions, and static-only class patterns.
What does static mean in a class?
- A **static member** belongs to the **class**, not to one object.
- **Static data** — one shared copy for all objects of that class.
- **Static function** — called on the class (or via object) but has **no
this** and can only use static data (directly). - **Real-life:** a school’s total student count on the notice board (shared) vs each student’s own marks (per object).
- **Real-life:** a factory’s “units produced today” counter shared by all machines.
| Kind | Belongs to | Per object? | Has this? |
|---|---|---|---|
| Normal data member | Each object | Yes — own copy | N/A |
| Static data member | Class (shared) | No — one copy | N/A |
| Normal member function | Called on an object | Uses that object | Yes |
| Static member function | Class utility | No instance needed | No |
Static variables (static data members)
- Declare inside the class with
static:static int count; - Define outside (older style):
int ClassName::count = 0; - C++17:
static inline int count = 0;can be initialized in-class. - Access:
ClassName::countorobj.count(still the same shared variable). - Common use: object counters, shared config, caches, ID generators.
#include <iostream>
using namespace std;
class Student {
private:
string name;
public:
static int count; // declaration — shared
Student(string n) : name(n) { count++; }
static int getCount() { return count; }
};
int Student::count = 0; // definition
int main() {
Student a("Asha"), b("Ravi"), c("Neha");
cout << Student::count << "\n"; // 3
cout << Student::getCount() << "\n"; // 3
return 0;
} Static local variables (inside functions)
- A
staticvariable **inside a function** is initialized once and **keeps its value** across calls. - Different from class static members — lifetime is the whole program, scope is the function.
- **Real-life:** a ticket counter machine that remembers the last number issued.
#include <iostream>
using namespace std;
int nextId() {
static int id = 0; // initialized once
return ++id;
}
int main() {
cout << nextId() << "\n"; // 1
cout << nextId() << "\n"; // 2
cout << nextId() << "\n"; // 3
return 0;
} Static member functions (static functions)
- Declared with
staticinside the class:static void showCount(); - Can be called **without an object**:
ClassName::showCount(); - **No
thispointer** — cannot access non-static members directly. - Can access static data members and other static functions.
- **Real-life:**
Math::max(a,b)utility — no need to create a Math object.
| Can access | Static function? | Normal function? |
|---|---|---|
| Static data members | Yes | Yes |
| Non-static data members | No (needs an object) | Yes via this |
| Call without object | Yes Class::f() | No |
this pointer | No | Yes |
#include <iostream>
using namespace std;
class Counter {
private:
static int value;
public:
static void reset() { value = 0; }
static void add(int x) { value += x; }
static int get() { return value; }
};
int Counter::value = 0;
int main() {
Counter::add(5);
Counter::add(3);
cout << Counter::get() << "\n"; // 8
Counter::reset();
cout << Counter::get() << "\n"; // 0
return 0;
} Static vs non-static (comparison)
- Use static for shared class-level state or utilities; use non-static for per-object data.
| Point | Non-static | Static |
|---|---|---|
| Memory | Each object has a copy | One shared copy |
| Access | Needs an object (usually) | Via Class:: (or object) |
this | Available in methods | Not available |
| Typical use | name, balance, speed | count, maxLimit, helpers |
| Lifetime | Object lifetime | Program lifetime (usually) |
Static classes in C++ (important note)
- C++ has **no
static classkeyword** like C#. - To get a similar design (“only utilities, no instances”), use one of these patterns:
- 1) A class with **only static members** + deleted constructors.
- 2) A **namespace** with free functions (often cleaner for pure utilities).
- 3)
struct/classof static constants and helpers. - **Real-life:** a toolbox bolted to the wall — you use tools without “creating a toolbox object” each time.
| Goal | C# style idea | C++ approach |
|---|---|---|
| No instances | static class Util | Delete ctors + only static members |
| Utility functions | Static methods | namespace Util { ... } or static methods |
| Shared constants | Static fields | static const / constexpr / inline static |
| Prevent inheritance | Sealed/static class | final class + deleted ctors (optional) |
#include <iostream>
#include <cmath>
using namespace std;
// "Static class" pattern in C++
class MathUtil final {
public:
MathUtil() = delete; // no objects
static int square(int x) { return x * x; }
static int max(int a, int b) { return (a > b) ? a : b; }
};
// Often even better for pure functions:
namespace MathNs {
inline int square(int x) { return x * x; }
}
int main() {
cout << MathUtil::square(5) << "\n";
cout << MathNs::square(6) << "\n";
// MathUtil m; // ERROR — constructor deleted
return 0;
} When to use static members
- Prefer instance data unless sharing is truly required.
| Situation | Prefer | Example |
|---|---|---|
| Count how many objects exist | Static variable | Student::count |
| Utility with no state | Namespace or static function | MathUtil::max |
| Per-student marks | Non-static data | marks member |
| Shared app config flag | Static / global carefully | App::debugMode |
| ID generator | Static local or static member | nextId() |
Advanced — Static Members
Initialization and ODR details
- Non-inline static data members need a single definition in a
.cpp(One Definition Rule). - C++17
inline staticallows in-class definition without a separate.cppline. static constexprmembers for compile-time constants are common.- Order of initialization across translation units for statics can be tricky — avoid depending on it across files.
class Config {
public:
static inline int version = 1; // C++17
static constexpr double PI = 3.14159; // compile-time
}; Static functions and access control
- Static member functions still obey
private/public. - A public static function can touch private static data — good for controlled shared state.
- Factory-style APIs:
static Account open(...);returning an object.
class Account {
private:
int id;
static int next;
Account(int i) : id(i) {}
public:
static Account open() { return Account(++next); }
int getId() const { return id; }
};
int Account::next = 1000; Thread safety warning (overview)
- Shared static data is global-ish state — concurrent writes need synchronization.
- C++11 guarantees safe initialization of function-local statics (magic statics) in a single-threaded init sense; still protect later mutations.
- Prefer immutable statics or clear ownership when writing multi-threaded code.
Static class pattern checklist
- Delete default/copy/move constructors if instances must never exist.
- Make the class
finalif inheritance adds no value. - Or simply use a namespace — often the best C++ idiom for free utilities.
- Do not overuse static mutable state — it can make testing harder.
Real-life models
- Library:
Bookobjects + statictotalBooks. - Game:
Enemy::aliveCountshared across enemies. - Logger: static
Logger::info(msg)without constructing a logger each time. - Settings:
AppConfig::getTheme()static accessor.
Tricky Interview Points
Q1) What is a static data member?
Answer A class member shared by all objects — only one copy exists for the class. Declared with static inside the class and typically defined outside (or inline static in C++17).
Q2) What is a static member function?
Answer A function belonging to the class that can be called without an object. It has no this pointer and cannot access non-static members directly.
Q3) Difference between static and non-static members?
Answer Non-static members belong to each object. Static members belong to the class and are shared. Static functions have no this.
Q4) Does C++ have static classes like C#?
Answer No static class keyword. Approximate with a class of only static members and deleted constructors, or preferably a namespace of free functions.
Q5) Can a static function access non-static data?
Answer Not directly. It would need an object instance passed in (or available otherwise) to access that object’s non-static members.
Q6) How do you count objects of a class?
Answer Use a static counter incremented in constructors and decremented in the destructor.
Q7) What is a static local variable?
Answer A variable declared static inside a function. It is initialized once and retains its value between calls.
Q8) How do you access a static member?
Answer Prefer ClassName::member. You can also use object.member, but it still refers to the shared class member.
Q9) What is inline static (C++17)?
Answer Allows defining/initializing a static data member inside the class without a separate out-of-class definition in a .cpp file.
Q10) Why might namespaces be better than a static utility class?
Answer Namespaces are the natural C++ place for free functions, avoid fake “no-instance class” boilerplate, and compose cleanly.
Q11) Can static members be private?
Answer Yes. Private static data is often exposed via public static getters/functions.
Q12) Is static data destroyed when objects are destroyed?
Answer No. Static data members typically live for the program duration, independent of individual object lifetimes.
Simple Programs
Object counter with static variable
#include <iostream>
#include <string>
using namespace std;
class Student {
string name;
public:
static int count;
Student(string n) : name(n) { ++count; }
~Student() { --count; }
static int getCount() { return count; }
};
int Student::count = 0;
int main() {
Student a("A"), b("B");
cout << Student::getCount() << "\n"; // 2
{
Student c("C");
cout << Student::getCount() << "\n"; // 3
}
cout << Student::getCount() << "\n"; // 2
return 0;
} Static local — ID generator
#include <iostream>
using namespace std;
int ticket() {
static int n = 100;
return n++;
}
int main() {
cout << ticket() << " " << ticket() << " " << ticket() << "\n";
return 0;
} Static member functions — Counter
#include <iostream>
using namespace std;
class Counter {
static int value;
public:
static void add(int x) { value += x; }
static int get() { return value; }
};
int Counter::value = 0;
int main() {
Counter::add(10);
cout << Counter::get() << "\n";
return 0;
} Static-only class pattern
#include <iostream>
using namespace std;
class StringUtil final {
public:
StringUtil() = delete;
static int length(const char* s) {
int n = 0;
while (s && s[n]) n++;
return n;
}
};
int main() {
cout << StringUtil::length("C++") << "\n"; // 3
return 0;
} Namespace alternative to static class
#include <iostream>
using namespace std;
namespace Geom {
inline double square(double x) { return x * x; }
}
int main() {
cout << Geom::square(4) << "\n";
return 0;
} Static vs instance data together
#include <iostream>
#include <string>
using namespace std;
class Player {
string name;
static int online;
public:
Player(string n) : name(n) { ++online; }
~Player() { --online; }
string getName() const { return name; }
static int getOnline() { return online; }
};
int Player::online = 0;
int main() {
Player p1("Sam"), p2("Alex");
cout << p1.getName() << "\n";
cout << "Online: " << Player::getOnline() << "\n";
return 0;
} inline static (C++17 style)
#include <iostream>
using namespace std;
class App {
public:
static inline int version = 2;
static void show() { cout << "v" << version << "\n"; }
};
int main() {
App::show();
App::version = 3;
App::show();
return 0;
} Problem Solving Tricks
- Static data = one shared copy; instance data = per object.
- Call static functions as ClassName::func().
- Static functions have no this — do not use instance fields directly.
- Define out-of-class statics (or use inline static in C++17).
- C++ has no static class keyword — delete ctors or use a namespace.
- Use static locals for simple persistent counters inside a function.
- Increment static count in ctor; decrement in dtor for live object counts.
- Prefer namespaces for pure utility collections.
- Keep mutable static shared state minimal — harder to test.
- Private static + public static getter = controlled shared access.
- obj.staticMember still refers to the shared class member.
- Remember static lifetime ≈ program lifetime for members/locals.
Practice Programs List
- Create Employee with static count; print count after creating/destroying objects.
- Write static local nextInvoiceNo() that returns increasing numbers.
- Implement MathUtil static-only class with square/max and deleted constructor.
- Rewrite MathUtil as a namespace and compare clarity.
- Add static getCount() that returns private static count.
- Show a compile error by accessing a non-static field from a static function.
- Build Logger::info(msg) as a static function writing to cout.
- Use inline static for a Config::debug flag (C++17).
- Combine instance name + static onlinePlayers in a GameUser class.
- Explain in comments: static member vs static local vs namespace function.
- Create a factory static Account::create() returning Account objects with unique ids.
- List three real apps where a shared static counter is useful.
- Demonstrate Class::x and obj.x referring to the same static.
- Discuss why overusing static mutable data can be a design smell.