cpp

examples

examples.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;
}
Examples - C++ Tutorial | DeepML