Classes and OOP

Classes and OOP

Classes, structs, access control, inheritance, virtual functions, and object design.

Classes and OOP

Class basics

class Rectangle {
public:
    Rectangle(double w, double h) : width_{w}, height_{h} {}
    double area() const { return width_ * height_; }

private:
    double width_{};
    double height_{};
};

struct vs class

Special member functions

Inheritance

class Shape {
public:
    virtual ~Shape() = default;
    virtual double area() const = 0;
};

class Circle : public Shape {
public:
    explicit Circle(double r) : radius_{r} {}
    double area() const override { return 3.14159 * radius_ * radius_; }

private:
    double radius_{};
};

Keywords to know

Best-practice reminders

Rule of zero and rule of five

class SocketOwner {
public:
    SocketOwner(SocketOwner&&) noexcept = default;
    SocketOwner& operator=(SocketOwner&&) noexcept = default;

    SocketOwner(const SocketOwner&) = delete;
    SocketOwner& operator=(const SocketOwner&) = delete;
};

Modern class features

struct Config {
    std::string host;
    int port{};
    auto operator<=>(const Config&) const = default;
};

Polymorphism alternatives

Object slicing

void show(Shape shape);  // takes by value

Rectangle rect{3.0, 4.0};
show(rect);  // derived data lost — always pass via reference or pointer

Polymorphic containers

std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Circle>(5.0));
shapes.push_back(std::make_unique<Rectangle>(3.0, 4.0));

Store polymorphic objects through smart pointers. Raw owning pointers in a container require manual cleanup and invite leaks.

Quick pitfall list

Example in practice

struct Widget {
    int id{};
};

int main() {
    Widget w{3};
    return w.id;
}

Try this variation

Add a member function that keeps the invariants next to the data. That is the simplest way to move from passive structs to useful types.

struct Point {
    int x{};
    int y{};

    int magnitude_squared() const {
        return x * x + y * y;
    }
};