cpp
examples
examples.cpp⚙️cpp
/**
* Object Relationships - Examples
* Compile: g++ -std=c++17 -Wall examples.cpp -o examples
*/
#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;
// ============================================================
// SECTION 1: COMPOSITION (Strong HAS-A)
// ============================================================
class Engine {
int horsepower;
public:
Engine(int hp) : horsepower(hp) { cout << " Engine(" << hp << "hp) created" << endl; }
~Engine() { cout << " Engine destroyed" << endl; }
void start() { cout << " Engine started" << endl; }
};
class Car {
Engine engine; // Composition - owns engine
string model;
public:
Car(const string& m, int hp) : engine(hp), model(m) {
cout << " Car(" << model << ") created" << endl;
}
~Car() { cout << " Car(" << model << ") destroyed" << endl; }
void start() {
cout << " Starting " << model << endl;
engine.start();
}
};
void demoComposition() {
cout << "--- Composition ---\n" << endl;
{
Car car("Tesla", 400);
car.start();
cout << "\n Leaving scope..." << endl;
}
cout << " (Engine destroyed with Car)" << endl;
}
// ============================================================
// SECTION 2: AGGREGATION (Weak HAS-A)
// ============================================================
class Player {
string name;
public:
Player(const string& n) : name(n) {}
string getName() const { return name; }
};
class Team {
string teamName;
vector<Player*> players; // Aggregation - doesn't own
public:
Team(const string& n) : teamName(n) {}
void addPlayer(Player* p) { players.push_back(p); }
void showRoster() {
cout << " Team " << teamName << ": ";
for (auto* p : players) cout << p->getName() << " ";
cout << endl;
}
// No delete in destructor - players exist independently
};
void demoAggregation() {
cout << "\n--- Aggregation ---\n" << endl;
Player p1("Alice"), p2("Bob"), p3("Charlie");
Team teamA("Red");
Team teamB("Blue");
teamA.addPlayer(&p1);
teamA.addPlayer(&p2);
teamB.addPlayer(&p2); // Bob on both teams!
teamB.addPlayer(&p3);
teamA.showRoster();
teamB.showRoster();
cout << " (Players outlive teams)" << endl;
}
// ============================================================
// SECTION 3: ASSOCIATION (Bidirectional)
// ============================================================
class Course;
class Student {
string name;
vector<Course*> courses;
public:
Student(const string& n) : name(n) {}
void enroll(Course* c);
string getName() const { return name; }
void showCourses();
};
class Course {
string title;
vector<Student*> students;
public:
Course(const string& t) : title(t) {}
void addStudent(Student* s) { students.push_back(s); }
string getTitle() const { return title; }
void showStudents() {
cout << " " << title << " students: ";
for (auto* s : students) cout << s->getName() << " ";
cout << endl;
}
};
void Student::enroll(Course* c) {
courses.push_back(c);
c->addStudent(this);
}
void Student::showCourses() {
cout << " " << name << " enrolled in: ";
for (auto* c : courses) cout << c->getTitle() << " ";
cout << endl;
}
void demoAssociation() {
cout << "\n--- Association ---\n" << endl;
Student alice("Alice"), bob("Bob");
Course math("Math"), physics("Physics");
alice.enroll(&math);
alice.enroll(&physics);
bob.enroll(&math);
alice.showCourses();
bob.showCourses();
math.showStudents();
}
// ============================================================
// SECTION 4: DEPENDENCY (Uses)
// ============================================================
class Document {
string content;
public:
Document(const string& c) : content(c) {}
string getContent() const { return content; }
};
class Printer {
public:
// Dependency - uses Document temporarily
void print(const Document& doc) {
cout << " Printing: " << doc.getContent() << endl;
}
};
class EmailSender {
public:
// Dependency - uses Document temporarily
void send(const Document& doc, const string& to) {
cout << " Sending '" << doc.getContent() << "' to " << to << endl;
}
};
void demoDependency() {
cout << "\n--- Dependency ---\n" << endl;
Document report("Q4 Report");
Printer printer;
EmailSender sender;
printer.print(report);
sender.send(report, "boss@company.com");
}
// ============================================================
// SECTION 5: COMPOSITION WITH SMART POINTERS
// ============================================================
class Wheel {
public:
Wheel() { cout << " Wheel created" << endl; }
~Wheel() { cout << " Wheel destroyed" << endl; }
};
class ModernCar {
unique_ptr<Engine> engine;
vector<unique_ptr<Wheel>> wheels;
public:
ModernCar() {
cout << " Building ModernCar..." << endl;
engine = make_unique<Engine>(300);
for (int i = 0; i < 4; ++i)
wheels.push_back(make_unique<Wheel>());
}
// Automatic cleanup!
};
void demoSmartPointers() {
cout << "\n--- Smart Pointer Composition ---\n" << endl;
{
ModernCar car;
cout << " Car ready!\n Leaving scope..." << endl;
}
cout << " All cleaned up automatically!" << endl;
}
// ============================================================
// SECTION 6: COMPOSITION OVER INHERITANCE
// ============================================================
// Bad: Inheritance for code reuse
class BadStack : public vector<int> {
// Exposes all vector methods!
};
// Good: Composition
class GoodStack {
vector<int> data; // Hidden implementation
public:
void push(int x) { data.push_back(x); }
void pop() { data.pop_back(); }
int top() const { return data.back(); }
bool empty() const { return data.empty(); }
size_t size() const { return data.size(); }
};
void demoCompositionOverInheritance() {
cout << "\n--- Composition Over Inheritance ---\n" << endl;
GoodStack stack;
stack.push(1);
stack.push(2);
stack.push(3);
cout << " Stack top: " << stack.top() << endl;
cout << " Stack size: " << stack.size() << endl;
cout << " (Clean interface, hidden implementation)" << endl;
}
// ============================================================
// MAIN
// ============================================================
int main() {
cout << "╔══════════════════════════════════════╗" << endl;
cout << "║ OBJECT RELATIONSHIPS - EXAMPLES ║" << endl;
cout << "╚══════════════════════════════════════╝" << endl;
demoComposition();
demoAggregation();
demoAssociation();
demoDependency();
demoSmartPointers();
demoCompositionOverInheritance();
cout << "\n=== Complete ===" << endl;
return 0;
}