05-association-and-modern-cpp.md

Association and Modern C++ Integration

Table of Contents

  1. Association: The Has-A Relationship
  2. Weak vs Strong Lifecycle (Aggregation vs Composition)
  3. Implementing Association in C++
  4. Modern C++ Smart Pointers

1. Association: The Has-A Relationship

While Inheritance defines an Is-A relationship (Monkey is-an Animal), Association defines a Has-A relationship.

A Has-A relationship occurs when a class uses an instance of another class as one of its own attributes. For example, if you have a Library class, it will contain a collection of Book objects. The library has books. A Car has an Engine.

Depending on how tightly bound these two objects are to each other's lifecycles, the "Has-A" relationship is split into two distinct types: Aggregation and Composition.


2. Weak vs Strong Lifecycle (Aggregation vs Composition)

FeatureAggregation (Weak)Composition (Strong)
Relationship Type"Has-A" (Loose ownership)"Has-A" (Strict death-do-us-part ownership)
Lifecycle DependencyIndependent. Child survives parent's deletion.Dependent. Child dies automatically with parent.
C++ ImplementationUses pointers or references (Base* or Base&) pointing to external objects.Uses direct member objects (Base obj) or allocates internally on creation.
CardinalityOften Many-to-Many (A professor can belong to multiple departments).Strictly One-to-One or One-to-Many (A room cannot belong to two separate houses).

3. Implementing Association in C++

Aggregation Example (Weak)

class Professor { public: string name; Professor(string n) : name(n) {} }; class Department { private: // Aggregation: The Department holds a POINTER to the Professor. // It does NOT own the Professor. Professor* prof; public: Department(Professor* p) : prof(p) {} ~Department() { // Notice we DO NOT delete the prof here! // The professor survives the closure of the department. } }; int main() { Professor* drSmith = new Professor("Dr. Smith"); Department* mathDept = new Department(drSmith); delete mathDept; // Math dept closes. // drSmith is STILL ALIVE and can join another department! delete drSmith; }

Composition Example (Strong)

class Engine { public: Engine() { cout << "Engine created\n"; } ~Engine() { cout << "Engine destroyed\n"; } }; class Car { private: // Composition: The Car DIRECTLY owns the Engine. Engine engine; public: Car() { cout << "Car created\n"; } ~Car() { cout << "Car destroyed\n"; } }; int main() { Car* myCar = new Car(); delete myCar; // When the car is deleted, the engine is AUTOMATICALLY destroyed. }

4. Modern C++ Smart Pointers

Raw pointers (*) cause massive headaches (memory leaks, dangling pointers) if you forget to delete them. Modern C++ (C++11 and up) solves this using Smart Pointers, which map perfectly to Association concepts!

1. std::unique_ptr (Perfect for Composition)

An exclusive ownership pointer. When the pointer goes out of scope, the object is automatically deleted. It cannot be copied.

#include <memory> class Car { private: // The Car exclusively owns the engine. Composition! std::unique_ptr<Engine> engine; public: Car() : engine(std::make_unique<Engine>()) {} // No need to manually delete engine in destructor! };

2. std::shared_ptr (Perfect for Aggregation)

Shared ownership. Multiple pointers can point to the same object. It uses a Reference Count. When the count drops to 0 (all departments are deleted), the professor is finally deleted.

#include <memory> class Department { private: std::shared_ptr<Professor> prof; public: Department(std::shared_ptr<Professor> p) : prof(p) {} }; int main() { std::shared_ptr<Professor> drSmith = std::make_shared<Professor>("Dr. Smith"); // Both Math and Physics share ownership of Dr. Smith Department math(drSmith); Department physics(drSmith); }