Capstone — Building a Small Project

Course 3 · Ch 6 — Track Finale
Capstone: Building a Small Project
A polymorphic shape inventory, combining nearly every chapter across all three C++ courses

Twenty-two chapters, one piece at a time. This closing chapter builds a small shape inventory — polymorphic shapes, RAII, templates, smart pointers, exceptions, and STL algorithms combined into one working, modern C++ program.

The Project — A Shape Inventory

Inventory: 3 shapes, total area 103.32 1. Circle — area 78.54 2. Rectangle — area 24.00 3. Circle — area 0.79

The Shape Hierarchy

cpp1-4/cpp1-5/cpp1-7: a Shape base class with virtual area() and name(), derived classes validating their own input in the constructor and throwing on invalid data (cpp2-6).

class Shape { public: virtual double area() const = 0; virtual std::string name() const = 0; virtual ~Shape() = default; }; class Circle : public Shape { double radius; public: Circle(double r) : radius(r) { if (r <= 0) throw std::invalid_argument("radius must be positive"); } double area() const override { return 3.14159 * radius * radius; } std::string name() const override { return "Circle"; } };

Exception Safety in the Constructors

Circle(-5.0) throws before construction ever completes — a real, direct application of cpp2-6's own constructor-exception material. No RAII resource is ever left half-acquired.

A Generic Repository<T> Template

cpp2-1's own templates, applied for real — a small, genuinely reusable class template, not shape-specific at all.

template<typename T> class Repository { std::vector<std::unique_ptr<T>> items; public: void add(std::unique_ptr<T> item) { items.push_back(std::move(item)); // cpp2-5's own move semantics } size_t size() const { return items.size(); } const std::unique_ptr<T>& operator[](size_t i) const { return items[i]; } };

Ownership via unique_ptr — No Slicing, Ever

Shapes are never stored or passed by value — only via unique_ptr<Shape>, deliberately avoiding cpp3-5's own object-slicing trap by construction. add() takes ownership via std::move, exactly cpp2-4's and cpp2-5's own material applied together.

Sorting With a Lambda

cpp2-3's std::sort plus cpp2-7's own lambda syntax, comparing shapes by area through their owning unique_ptrs.

std::sort(shapes.begin(), shapes.end(), [](const auto &a, const auto &b) { return a->area() < b->area(); });

const-Correctness Throughout

cpp2-8's own discipline, applied everywhere: area()/name() are const; Repository's own size()/operator[] are const-correct too — nothing in this project mutates state it doesn't need to.

Where Each Piece Came From

PieceChapter
Shape hierarchy, RAII, polymorphismcpp1-4, cpp1-5, cpp1-7
Exception-validated constructorscpp2-6
Repository<T> templatecpp2-1
unique_ptr ownership, no slicingcpp2-4, cpp3-5
std::move into the repositorycpp2-5
std::sort with a lambdacpp2-3, cpp2-7
const-correctness throughoutcpp2-8

What's Still Out of Scope, Honestly

No multiple inheritance was needed — cpp3-1's own material simply wasn't necessary here, a single hierarchy sufficed, itself a realistic outcome. No concurrency (cpp3-4) — this is a single-threaded tool. No hand-written Rule of Five anywhere — the entire project follows the Rule of Zero throughout, a deliberate demonstration that modern C++ rarely needs it. C++20 concepts (cpp3-2) weren't used either, kept to plain templates for broader compiler compatibility.

The throughline, restated
Every piece of this capstone is a direct, unmodified application of a chapter's own material — nothing new was introduced here, matching the same pattern the C track's own capstone (c3-6) established.
Real capability, not Rust's compile-time guarantees
This capstone is genuinely modern, safe-by-convention C++ — RAII everywhere, no raw new/delete, no slicing, exception-safe construction. But nothing here is enforced by the compiler the way Rust's ownership and borrow rules would be. The discipline is real; it's still discipline, not a guarantee.

Closing the Course & Track

From cpp1-1's compile model to a real, polymorphic, exception-safe, template-based, RAII-everywhere program — every chapter added one piece of real capability C never had, while this course's own repeated Rust comparisons kept one honest question in view: what does the language enforce, versus what does it merely make possible? The genuine convergence points along the way — RAII/Drop, monomorphization, unique_ptr/Box, shared_ptr/Rc, lambdas/closures — show two languages solving similar problems from different starting philosophies. That comparison, sustained across 44 chapters spanning both tracks, is the actual lesson.

Coding Challenges

Challenge 1

Identify which specific chapter each of the following pieces of the shape inventory came from: (a) the Repository template, (b) the exception thrown from Circle's constructor, (c) sorting shapes by area.

📄 View solution
Challenge 2

Explain why storing shapes as std::vector (by value) instead of std::vector> would break this capstone's own design, tying your answer directly to cpp3-5's own object-slicing material.

📄 View solution
Challenge 3

Across the entire C++ track, name the single idea that recurs most often, and explain in your own words why understanding it deeply matters more than memorizing any individual keyword or syntax rule.

📄 View solution

Chapter 6 Quick Reference — Course & Track Complete

  • The shape inventory combines: polymorphism (cpp1-7), RAII (cpp1-5), templates (cpp2-1), smart pointers (cpp2-4), move semantics (cpp2-5), exceptions (cpp2-6), lambdas (cpp2-7), const-correctness (cpp2-8), and avoids slicing (cpp3-5)
  • Still out of scope, honestly: multiple inheritance, concurrency, hand-written Rule of Five, C++20 concepts — none were needed here
  • Real capability, not compiler-enforced guarantees — the discipline is genuine, but still discipline, not Rust's kind of guarantee
  • Course 3 complete — C++ Advanced, 6 chapters
  • Full C++ track complete — Fundamentals + Intermediate + Advanced, 23 chapters across 3 courses