C++ OOP Track

Learning Objectives

Review every C++ OOP mechanism in one place and know which module covers it in depth.

Write idiomatic modern C++ classes (C++20/23).

Prerequisites: Stages 1–2.

Intuition and Definition

C++ gives you value semantics by default, deterministic destruction, zero-overhead abstractions and both run-time and compile-time polymorphism — and expects you to manage ownership explicitly.

Classes, access class/struct, public/protected/private, friend constructors, initializer lists, delegating, explicit, destructors

public/protected/private inheritance, virtual bases, final

virtual, override, pure virtual, vtables almost all overloadable, <=> templates, concepts, CRTP

RAII, unique_ptr/shared_ptr/weak_ptr, Rule of 0/3/5, move semantics exceptions, noexcept, std::expected RTTI: typeid, dynamic_cast sizeof, alignment, EBO, Pimpl

Why It Matters

C++ is the main OO language in embedded systems, automotive ECUs, games, finance and infrastructure software — exactly where object lifetime and performance matter most.

Syntax and Language Notes

Modern guidelines (C++ Core Guidelines): prefer values and unique_ptr, follow the Rule of Zero, mark single-argument constructors explicit, use override, make polymorphic bases' destructors virtual (or protected), avoid owning raw pointers, prefer std::expected/exceptions consistently, and constrain templates with concepts.

Complete Example

A compact tour: an abstract interface, RAII ownership, a value type with operators, a constrained template, move semantics, exceptions and RTTI.

#include <concepts>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <typeinfo>
#include <vector>

struct Celsius {                                              // value type with operators
    double v;
    auto operator<=>(const Celsius&) const = default;
    Celsius operator+(Celsius o) const { return {v + o.v}; }
};
std::ostream& operator<<(std::ostream& os, Celsius c) { return os << c.v << " C"; }

class Sensor {                                                // interface
public:
    virtual ~Sensor() = default;
    virtual Celsius read() const = 0;
    virtual std::string id() const = 0;
};

class Thermistor final : public Sensor {
    std::string id_;
    Celsius offset_;
public:
    explicit Thermistor(std::string id, Celsius off = {0}) : id_(std::move(id)), offset_(off) {}
    Celsius read() const override { return Celsius{88.5} + offset_; }
    std::string id() const override { return id_; }
};

class Rack {                                                  // owns sensors: Rule of Zero, move-only
    std::vector<std::unique_ptr<Sensor>> sensors_;
public:
    void add(std::unique_ptr<Sensor> s) {
        if (!s) throw std::invalid_argum
…
coolant: 90 C
oil: 88.5 C
hot sensors: 1
dynamic type is Thermistor: 1
error: null sensor

Step-by-Step Walkthrough

Celsius is a value type; defaulted <=> gives all comparisons.

Sensor is a pure interface with a virtual destructor; Thermistor is final.

Rack owns sensors through unique_ptr: it is automatically move-only and cleans up deterministically.

count accepts any callable satisfying std::predicate<const Sensor&>.

RTTI confirms the dynamic type; invalid input throws.

Common Mistakes

C++-specific pitfalls covered in this course: slicing (8), missing virtual destructor (4), owning raw pointers (13), shared_ptr cycles (13), dangling references/views (13), initializer order (5), name hiding (7), default arguments on virtuals (35), const members blocking assignment (59), side effects in assert (54).

Trade-offs and Alternatives

C++ gives control and performance at the price of complexity; much of modern C++ style is about *not* using features (raw new, manual memory management, deep inheritance).

Real-World Use

AUTOSAR Adaptive, game engines (Unreal), browsers (Chromium), databases, trading systems, robotics (ROS 2).

Practice

Q1. (Easy) Why is Rack move-only without any code?

Answer: Its std::vector<std::unique_ptr<Sensor>> member is move-only, so the implicitly generated copy operations are deleted.

Q2. (Medium) What does final on Thermistor enable besides preventing derivation?

Answer: Devirtualization: calls through a Thermistor reference can be resolved statically.

Q3. (Advanced) List three things you'd check in a C++ class review.

Answer: Ownership (Rule of Zero/Five, no owning raw pointers), polymorphic base correctness (virtual or protected destructor, override, no slicing), and exception safety/noexcept on moves and destructors (plus explicit constructors and const-correctness).

Interview Question

Q1. "What makes modern C++ OOP different from 'C with classes'?"

Answer: RAII and smart pointers instead of manual new/delete, value semantics with move semantics, the Rule of Zero, override/final, generic programming with templates and concepts (often replacing inheritance), std::variant/std::optional/std::expected for sum types and errors, ranges, and constexpr computation — with inheritance reserved for genuine run-time polymorphism.

Quick Quiz

Q1. Default copy semantics of C++ class objects?

Answer: Value (memberwise copy).

Q2. Which smart pointer by default?

Answer: std::unique_ptr.

Q3. What does override guarantee?

Answer: A compile error if the function doesn't override a base virtual.

Summary

C++ OOP = value semantics + RAII + explicit ownership + virtual and template polymorphism.

Related: Modules 2–17, 55–58.