Skip to content

Classes & Objects

Classes are the heart of Object-Oriented Programming (OOP) in C++. They encapsulate data and behavior into a single unit.

Class vs. Struct

In C++, class and struct are almost identical. - class: Members are private by default. - struct: Members are public by default.

Use struct for simple data containers (PODs) and class for objects with invariants and logic.

struct Point {
    int x;
    int y;
};

class Account {
    double balance; // private
public:
    void deposit(double amount);
};

Access Specifiers

  • public: Accessible from anywhere.
  • private: Accessible only from within the class.
  • protected: Accessible from within the class and derived classes.
1
2
3
4
5
6
7
8
class Sensor {
public:
    void read() { /* ... */ } // Public interface

private:
    int raw_value; // Internal data
    void calibrate() { /* ... */ } // Internal helper
};

Static Members

Static members belong to the class itself, not to any specific object instance.

Static Variables

Shared across all instances. Must be defined outside the class (unless inline or constexpr).

1
2
3
4
5
6
7
8
class Counter {
public:
    static int count;
    Counter() { count++; }
};

// Definition
int Counter::count = 0;

Static Functions

Can be called without an object. Can only access static variables.

1
2
3
4
5
6
class Math {
public:
    static int add(int a, int b) { return a + b; }
};

int sum = Math::add(1, 2);

Unions

A union is a special class type where all members share the same memory location. Only one member can be active at a time.

1
2
3
4
5
6
7
8
9
union Data {
    int i;
    float f;
    char c;
};

Data d;
d.i = 10;
// d.f is now garbage (or a reinterpretation of the bits of 10)

Modern C++: Prefer std::variant over union for type safety.

Constructors & Destructors

  • Constructor: Called when an object is created. Used to initialize invariants.
  • Destructor: Called when an object is destroyed. Used to release resources (RAII).
1
2
3
4
5
6
7
8
9
class GPIO {
public:
    GPIO(int pin) {
        // Open GPIO pin
    }
    ~GPIO() {
        // Close GPIO pin
    }
};

Member Initializer Lists

Always use member initializer lists to initialize member variables. It is more efficient than assignment inside the constructor body.

class User {
    std::string name;
    int age;

public:
    // Preferred
    User(const std::string& n, int a) : name(n), age(a) {}

    // Avoid (Constructs empty string, then assigns)
    // User(const std::string& n, int a) {
    //     name = n;
    //     age = a;
    // }
};

Const Member Functions

If a member function does not modify the object, mark it as const. This allows it to be called on const objects.

1
2
3
4
5
6
7
class Circle {
    double radius;
public:
    double get_area() const { // Promise not to change radius
        return 3.14 * radius * radius;
    }
};

The Rule of Five (Modern C++)

If you manage a resource (like a raw pointer), you likely need to define or delete these five special member functions:

  1. Destructor
  2. Copy Constructor
  3. Copy Assignment Operator
  4. Move Constructor
  5. Move Assignment Operator
class Buffer {
public:
    Buffer() = default;
    ~Buffer() { /* free memory */ }

    // Disable copying (Unique ownership)
    Buffer(const Buffer&) = delete;
    Buffer& operator=(const Buffer&) = delete;

    // Enable moving
    Buffer(Buffer&& other) noexcept { /* transfer ownership */ }
    Buffer& operator=(Buffer&& other) noexcept { /* transfer ownership */ }
};