OOP Quick Reference
C++ OOP cheatsheet — classes, access control, inheritance, virtual functions, abstract classes, and Rule of Five summary.
Class Anatomy
cpp
class Widget {
public: // public interface
Widget(int id, std::string name); // constructor
~Widget(); // destructor
Widget(const Widget&); // copy constructor
Widget& operator=(const Widget&); // copy assignment
Widget(Widget&&) noexcept; // move constructor
Widget& operator=(Widget&&) noexcept; // move assignment
int id() const; // const getter
void set_name(std::string);// setter
void render() const; // behavior
protected: // accessible in subclasses
void on_resize();
private: // implementation detail
int id_;
std::string name_;
};Access Control
cpp
class Foo {
public: // anyone
void use();
protected: // Foo + derived classes
void helper();
private: // Foo only
int data_;
friend class Bar; // Bar can access private
friend void baz(Foo&); // baz can access private
};Constructors
cpp
struct Point {
int x, y;
Point() : x{0}, y{0} {} // default
Point(int x, int y) : x{x}, y{y} {} // parameterized
Point(const Point&) = default; // copy — explicit default
explicit Point(int v) : x{v}, y{v} {} // prevent implicit conversion
// Delegating (C++11)
Point(int v) : Point{v, v} {}
};
// Aggregate initialization (no user-provided ctor needed)
struct Color { float r, g, b; };
Color red{1.0f, 0.0f, 0.0f};
Color blue{.b = 1.0f}; // C++20 designated initInheritance
cpp
struct Base {
virtual void draw() const = 0; // pure virtual
virtual void update() {} // virtual with default
virtual ~Base() = default; // always virtual dtor!
};
struct Derived : public Base {
void draw() const override final { } // override + final
// update() inherited from Base
};
struct Leaf final : Derived { }; // no further derivationRule of Five
cpp
class Resource {
public:
~Resource() // 1. destructor
Resource(const Resource&) // 2. copy ctor
Resource& operator=(const Resource&) // 3. copy assign
Resource(Resource&&) noexcept // 4. move ctor
Resource& operator=(Resource&&) noexcept // 5. move assign
};
// Rule of Zero: if members handle themselves, declare none:
class Modern {
std::unique_ptr<Foo> foo_; // unique_ptr handles move+destroy
std::string name_; // string handles copy+move
// No destructor/copy/move needed!
};Virtual Dispatch
cpp
struct Animal {
virtual void speak() const = 0;
virtual ~Animal() = default;
};
struct Dog : Animal { void speak() const override { puts("Woof"); } };
struct Cat : Animal { void speak() const override { puts("Meow"); } };
std::vector<std::unique_ptr<Animal>> animals;
animals.push_back(std::make_unique<Dog>());
animals.push_back(std::make_unique<Cat>());
for (const auto& a : animals)
a->speak(); // dynamic dispatch — Woof, MeowOperator Overloading Summary
cpp
// Member: =, [], (), ->, (unary)
// Free: +, -, *, /, ==, !=, <, >, <<, >>
struct Vec2 { float x, y; };
Vec2 operator+ (Vec2 a, Vec2 b) { return {a.x+b.x, a.y+b.y}; }
Vec2& operator+=(Vec2& a, Vec2 b) { a.x+=b.x; a.y+=b.y; return a; }
bool operator==(const Vec2& a, const Vec2& b) = default; // C++20
auto operator<=>(const Vec2&, const Vec2&) = default; // C++20
std::ostream& operator<<(std::ostream& os, const Vec2& v) {
return os << '(' << v.x << ',' << v.y << ')';
}Static Members
cpp
class Counter {
static int count_; // shared across all instances
public:
Counter() { ++count_; }
~Counter() { --count_; }
static int count() { return count_; }
static void reset() { count_ = 0; }
// C++17: inline static (define in header)
inline static int instances = 0;
};
int Counter::count_ = 0; // definition in .cpp
Counter::count(); // no object neededInterfaces (Abstract Base Classes)
cpp
struct Drawable {
virtual void draw(Canvas&) const = 0;
virtual BoundingBox bounds() const = 0;
virtual bool hit_test(Point pt) const { return bounds().contains(pt); }
virtual ~Drawable() = default;
};
struct Updateable {
virtual void update(float dt) = 0;
virtual ~Updateable() = default;
};
// Multiple interface inheritance
struct Sprite : public Drawable, public Updateable {
void draw(Canvas& c) const override { /* ... */ }
BoundingBox bounds() const override { /* ... */ }
void update(float dt) override { /* ... */ }
};Composition vs Inheritance
cpp
// Prefer composition ("has-a") over inheritance ("is-a")
// Inheritance: tight coupling, fragile base class
class LoggedVector : public std::vector<int> {
// BAD: std::vector has no virtual dtor!
};
// Composition: wraps, controls interface
class LoggedVector {
std::vector<int> data_;
public:
void push_back(int x) {
log("push_back");
data_.push_back(x);
}
// delegate only the interface you need
};