3B Infrastructure home

All subjects

Software Engineering Design (C++)

Designing software with C++: objects and polymorphism, safe resource handling, and reusable design patterns. Press play on any sketch to watch it happen.

1 Classes and polymorphism

A class bundles data with the functions that act on it, and hides the details. Polymorphism lets code work with a general type while each object does the right thing for itself.

  • Encapsulation: keep data private and expose a small public interface.
  • Inheritance: a derived class is a more specific version of its base.
  • Virtual function: the object's real type picks which version runs.
  • Composition: often better than inheritance: build from parts.
class Shape {
public:
    virtual ~Shape() = default;
    virtual double area() const = 0;
};

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

UML class diagram

shape->area()ShapeCirclearea = πr²Squarearea = w²is ais a

1/4 The calling code only knows it has a Shape.

Rule of thumb: Prefer "has a" over "is a". Deep inheritance trees are hard to change.

2 RAII and smart pointers

RAII ties a resource to an object's lifetime. The constructor acquires it and the destructor releases it, so cleanup happens automatically, even if an exception is thrown.

  • std::unique_ptr: one owner, freed automatically when it goes out of scope.
  • std::shared_ptr: shared ownership with a reference count.
  • Beyond memory: files, locks and sockets all follow the same pattern.
  • Rule of zero: let library types manage resources so you write no destructor at all.
void save() {
    auto sensor = std::make_unique<Sensor>();
    sensor->read();          // may throw
}                            // freed here, always

Lifetime diagram

Enter functionread() throws!Leave functionSensor memory

1/4 A raw pointer: new Sensor runs on the way in.

Rule of thumb: If you are typing new or delete in modern C++, there is usually a better way.

3 Design principles and patterns

Design patterns are named solutions to problems that keep coming up. SOLID principles are guidelines for keeping classes easy to change. Both exist to reduce coupling.

  • Single responsibility: a class should have one reason to change.
  • Open/closed: add behaviour by extending, without editing working code.
  • Dependency inversion: depend on interfaces, not on concrete classes.
  • Observer: objects subscribe to be told when something changes.
  • Strategy and factory: swap an algorithm at runtime, and hide how objects are created.

Sequence of messages

Sensor(subject)DisplayLogger

1/4 The display and the logger subscribe to the sensor.

Rule of thumb: Use a pattern to solve a problem you have, not to show that you know it.