Classes and Objects¶
Classes are the core construct for object-oriented programming (OOP) in C++. They allow you to bundle state (member variables) and behavior (member functions) into self-contained, user-defined types that enforce system invariants and encapsulation.
1. Classes vs. Structs¶
In C++, class and struct are virtually identical under the hood. The only differences are:
- class: Members and base class inheritance are private by default.
- struct: Members and base class inheritance are public by default.
Guideline:¶
- Use
structfor passive data containers without internal logic or invariants (often called Plain Old Data, or POD). - Use
classwhen the object needs to control access to its internal state to prevent invalid modifications (enforcing invariants).
2. Access Specifiers and Encapsulation¶
Encapsulation hides internal implementation details and protects the integrity of an object's state. C++ provides three access specifiers:
- public: The member is accessible from outside the class. Represents the class's public API interface.
- private: The member is only accessible from within functions belonging to the same class. Used for state variables and helper functions.
- protected: The member is accessible within the class itself and any child classes inheriting from it.
3. Object Lifetime: Constructors and Destructors¶
Constructors¶
Constructors initialize the object when it is allocated in memory. They have the same name as the class and do not specify a return type. - Default Constructor: Takes no arguments. - Parameterized Constructor: Takes arguments to initialize custom values. - Delegating Constructor (C++11): A constructor can call another constructor of the same class to avoid duplicate code.
In-Class Initializers¶
You can specify default values directly in the variable declarations within the class header. These are overridden if a constructor initializes the variable.
Member Initializer Lists¶
Always use member initializer lists instead of assigning values inside the constructor body.
[!WARNING] Initialization Order Warning: Member variables are initialized in the order they are declared in the class header, not the order they appear in the member initializer list. To avoid subtle bugs, always write your initializer list in the same order as the declarations.
4. Constant Member Functions¶
If a member function only reads data but does not modify the object's state, mark it as const. The compiler will block any modifications inside the function, and it allows the function to be called on const objects.
5. Static Members¶
static members are shared across all instances of a class. They belong to the class namespace itself, rather than any individual instance object.
Static Member Variables¶
Since they are shared, they must be defined in a single source file outside the class declaration, or declared as inline static in C++17 to initialize them directly in the header.
Static Member Functions¶
These functions do not receive the implicit this pointer and can only access other static variables or functions. They can be called without instantiating the class.
6. Managing Resources: The Rule of Three and Five¶
If your class allocates raw heap memory or holds system resources directly, you must manage how it is copied or moved.
The Rule of Three (Legacy C++98)¶
If you define a custom Destructor, Copy Constructor, or Copy Assignment Operator, you almost certainly need to define all three to manage deep copies.
The Rule of Five (Modern C++11)¶
With the introduction of move semantics, the Rule of Three is expanded to the Rule of Five. To prevent expensive copy operations, you should also implement the Move Constructor and Move Assignment Operator.
The Rule of Zero¶
In Modern C++, you should design your classes so that they do not handle raw resources directly. By using smart pointers (std::unique_ptr) and standard library containers (std::vector, std::string), the compiler automatically generates the correct copy/move constructors for you, eliminating the need to write them yourself.
Related Guides¶
- Memory Management — Understanding heap allocations, RAII, and smart pointers.
- Operator Overloading — Overloading relational and assignment operators.