A structured set of C++ object-oriented programming exercises, organized by topic. Each numbered lesson folder contains worked examples you can read/run and a homework set for students to complete. Written for a mixed audience — complete beginners through experienced engineers brushing up on C++ specifics.
OOP is not something you memorize. It is something you deeply understand and learn to build with.
This is a complete theoretical and practical guide to Object-Oriented Programming designed to take you from the basics to a deep, practical mastery of OOP — something most resources fail to provide.
Start from the fundamentals. Understand why OOP exists, how its concepts actually work, and how to apply them in real software. Then reinforce that understanding through practical implementations and increasingly complex problems.
OOP has a reputation for being difficult — not only for beginners, but even for experienced developers.
Many experienced developers jump straight into Design Patterns and SOLID principles without first developing a deep understanding of OOP itself. That often turns into memorizing rules instead of understanding the ideas behind them.
Master OOP first, and Design Patterns and SOLID become much easier to understand.
You can learn syntax without mastering OOP.
But sooner or later, serious software projects demand it.
Backend. Frontend. Mobile. Game development. ML/AI. Large-scale systems.
The tools and frameworks change. The fundamental concepts don't.
Don't just learn how to use OOP. Understand it deeply enough to design with it.
Learn the theory. Build the concepts. Practice the patterns. Master OOP.
The material is organized progressively — each lesson builds on the previous one.
Start here. The foundations everything else is built on:
- Classes and objects
- Constructors, including defaulted constructors
- Encapsulation via setters and getters
- Splitting a class across multiple files
- The
->pointer-call notation, thethispointer, andstructvsclass - Destructors, and constructor/destructor order
- Practical data structures (homework): linked list, stack, queue, binary search tree
How classes extend one another, and what that actually costs and buys you:
- Base and derived classes, protected members
- Access specifiers (
public/protected/privateinheritance) - Private inheritance
- Constructors and destructors across a hierarchy (default, custom, copy)
- Reused (hidden) symbols in inheritance
One of the most powerful — and most misunderstood — ideas in OOP:
- Static vs. dynamic binding
- Object slicing and polymorphic collections
override, and overloading vs. overriding vs. hiding- Virtual destructors and the
static/finalkeywords - Pure virtual functions, abstract classes, and abstract classes as interfaces
- Compile-time vs. run-time polymorphism
1-CLASSES-OBJECTS-AND-DATA-STRUCTURES/ classes, objects, and 4 data structures (linked list, stack, queue, BST)
2-INHERITANCE/ base/derived classes, access control, constructors & destructors
3-POLYMORPHISM/ virtual functions, abstract classes, static/dynamic bindingGit is a version-control system — a time machine for your code. It lets you:
- Commit snapshots of your work.
- Revert to any earlier state.
- Experiment safely on branches.
GitHub hosts Git repositories in the cloud and adds collaboration tools:
- Private/public storage for your code.
- Pull requests and code review.
- Issue tracking and an online portfolio.
A fork is your own personal copy of someone else's repository, created on GitHub with one click. It lives under your own account and is completely independent — you can edit, commit, and push to it freely without touching the original.
Why fork? You don't have write access to this repo. Forking gives you a copy you fully own, so you have somewhere to save your homework solutions as commits.
Cloning downloads a copy of a repository from GitHub onto your own computer, so you have real files on disk you can open in an editor, compile, and run.
Why clone? A fork only exists on GitHub's servers. You need a local copy to actually write
and test code — cloning creates that local copy and wires it up (as origin) so you can push
your changes back to your fork.
Any C++17-capable compiler works. Examples below use g++, but any option gets you there.
macOS
xcode-select --installThis installs Clang (aliased as g++) via the Xcode Command Line Tools. Verify it worked:
g++ --versionWindows — recommended: WSL (a real Linux environment inside Windows)
Open PowerShell as Administrator and run:
wsl --installRestart your computer when prompted, then open Ubuntu from the Start menu and follow the "Ubuntu / Debian" steps below inside it. This gets you the exact same commands as macOS/Linux users, with no PATH setup.
Windows — alternative: MSYS2 (native, no restart required)
In PowerShell:
winget install -e --id MSYS2.MSYS2Then open MSYS2 UCRT64 from the Start menu and run:
pacman -Syu --noconfirm
pacman -S --noconfirm mingw-w64-ucrt-x86_64-gccAdd C:\msys64\ucrt64\bin to your PATH (Windows Settings → Edit the system environment
variables → Environment Variables → edit Path → New → paste it in), then open a new
terminal and verify:
g++ --versionUbuntu / Debian
sudo apt update && sudo apt install -y build-essentialVerify it worked:
g++ --versionmacOS
brew install gitWindows
- Download Git for Windows: https://git-scm.com/download/win
- Run the installer and accept the defaults.
- Verify installation:
git --versionUbuntu / Debian
sudo apt update
sudo apt install gitGit stamps every commit with a name and email — set these once per machine:
git config --global user.name "Your Name"
git config --global user.email "you@example.com"Click Fork on github.com/rusterman/cpp-oop-examples-and-exercises to create your own copy under your GitHub account. You'll work and commit inside your fork, not the original.
Replace <your-username> with your GitHub username:
git clone https://github.com/<your-username>/cpp-oop-examples-and-exercises.git
cd cpp-oop-examples-and-exercisesOptionally, add the original repo as upstream so you can pull in future updates:
git remote add upstream https://github.com/rusterman/cpp-oop-examples-and-exercises.git
git remote -v # origin = your fork, upstream = originalNo build system is required — each example/homework compiles standalone:
cd 2-INHERITANCE/examples/02-protected-members
g++ -std=c++17 -Wall -o main main.cpp
./main- Go in lesson order —
1-CLASSES-OBJECTS-AND-DATA-STRUCTURES→2-INHERITANCE→3-POLYMORPHISM. Each builds on the last. - Read the lesson's
README.mdfirst for the topic list and, where included, a diagram giving you the big picture before the code. - Study every file in
examples/in order, numbered01,02, ... Read the code, run it, change something and re-run it — don't just read. - Then work through
homework/one exercise at a time, in numeric order. Each file name hints at what it's testing (e.g.homework-05-online-shop-system.cpp). - Don't modify anything under
examples/. Keep it untouched so you can always diff your solution against the original reference. Compiled binaries, IDE settings, and OS files (.DS_Store,.idea/,.vscode/,*.exe, extensionless build output, etc.) are already excluded via.gitignore— you shouldn't need to touch it.
- Don't just read. Reading code creates familiarity; writing code creates understanding.
- Don't memorize. If you understand why something works, you don't need to memorize it.
- Don't skip the exercises. The examples show you how; the exercises test whether you understand why.
- Don't rush to Design Patterns and SOLID. Master objects, classes, encapsulation, inheritance, and polymorphism first — patterns and principles click far faster once those are second nature.
Use one branch per person, named after your GitHub username, so your solutions are easy to find and never collide with anyone else's fork history:
| Step | Command |
|---|---|
| Create your solution branch | git checkout -b solutions/<your-username> |
| Work locally, commit per exercise | git add .git commit -m "2: homework 03 - multiple inheritance" |
| Push your branch to your fork | git push -u origin solutions/<your-username> |
Replace <your-username> with your actual GitHub username. Commit each homework exercise
separately with a clear message (<lesson-number>: homework <NN> - <short description>) so your
progress is easy to follow. Once pushed, you can open a pull request from
solutions/<your-username> into your own fork's main for a clean, reviewable diff of your work.
The goal isn't just to finish the exercises — it's to reach the point where you can look at a real software problem and naturally think: what are the objects, what should they own, what should they do, and how should they interact? That's when you stop using OOP and start thinking in OOP.
