cpp
exercises
exercises.cpp⚙️cpp
/**
* Object Relationships - Exercises
* Compile: g++ -std=c++17 -Wall exercises.cpp -o exercises
*/
#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;
// ============================================================
// Exercise 1: Composition ⭐
// ============================================================
// TODO: Create Heart and Brain classes
// TODO: Create Human that composes Heart and Brain
// Heart and Brain should be destroyed with Human
void exercise1() {
// Human h("Alice");
// h.think(); // Brain::process()
// h.pump(); // Heart::beat()
cout << "(Implement Human with Heart and Brain composition)" << endl;
}
// ============================================================
// Exercise 2: Aggregation ⭐⭐
// ============================================================
// TODO: Create Book and Library
// Library aggregates Books (doesn't own them)
// Same book can be in multiple libraries
class Book {
string title;
public:
Book(const string& t) : title(t) {}
string getTitle() const { return title; }
};
// TODO: Implement Library with vector<Book*>
void exercise2() {
Book b1("C++ Primer"), b2("Design Patterns");
// Library lib1("Main"), lib2("Branch");
// lib1.addBook(&b1); lib1.addBook(&b2);
// lib2.addBook(&b1); // Same book in both
cout << "(Implement Library aggregation)" << endl;
}
// ============================================================
// Exercise 3: Association ⭐⭐
// ============================================================
// TODO: Create Doctor and Patient with bidirectional association
// Doctor knows their patients
// Patient knows their doctors
void exercise3() {
// Doctor doc("Dr. Smith");
// Patient p1("Alice"), p2("Bob");
// doc.addPatient(&p1);
// doc.addPatient(&p2);
// p1.addDoctor(&doc);
cout << "(Implement Doctor-Patient association)" << endl;
}
// ============================================================
// Exercise 4: Dependency ⭐
// ============================================================
class Message {
string text;
public:
Message(const string& t) : text(t) {}
string getText() const { return text; }
};
// TODO: Create Encryptor that encrypts a Message (dependency)
// TODO: Create Logger that logs a Message (dependency)
void exercise4() {
Message msg("Hello World");
// Encryptor enc;
// cout << enc.encrypt(msg) << endl; // Uses Message temporarily
cout << "(Implement dependency relationship)" << endl;
}
// ============================================================
// Exercise 5: Smart Pointer Composition ⭐⭐
// ============================================================
// TODO: Create Computer with unique_ptr to CPU, RAM, GPU
// All components created and destroyed with Computer
void exercise5() {
// Computer pc;
// pc.run(); // Uses all components
cout << "(Implement Computer with smart pointers)" << endl;
}
// ============================================================
// Exercise 6: Composition vs Inheritance ⭐⭐⭐
// ============================================================
// TODO: Refactor this inheritance to composition
class BadLogger {
public:
void log(const string& msg) { cout << msg << endl; }
};
// Bad: Using inheritance for code reuse
class BadService : public BadLogger {
public:
void doWork() {
log("Working..."); // Inherited
}
};
// TODO: Create GoodService using composition instead
void exercise6() {
// GoodService service;
// service.doWork();
cout << "(Refactor to composition)" << endl;
}
// ============================================================
// Exercise 7: Full System ⭐⭐⭐
// ============================================================
// Design a simple school system:
// - School COMPOSES Departments (owns them)
// - Department AGGREGATES Teachers (doesn't own)
// - Teacher ASSOCIATES with Students (bidirectional)
// - Teacher uses Classroom (dependency)
void exercise7() {
// School school("Tech High");
// school.addDepartment("Math");
// school.addDepartment("Science");
// ... demonstrate all relationships
cout << "(Design school system with all relationship types)" << endl;
}
// ============================================================
// MAIN
// ============================================================
int main() {
cout << "=== Object Relationships Exercises ===" << endl;
cout << "\nEx1: Composition" << endl;
exercise1();
cout << "\nEx2: Aggregation" << endl;
exercise2();
cout << "\nEx3: Association" << endl;
exercise3();
cout << "\nEx4: Dependency" << endl;
exercise4();
cout << "\nEx5: Smart Pointers" << endl;
exercise5();
cout << "\nEx6: Composition vs Inheritance" << endl;
exercise6();
cout << "\nEx7: Full System" << endl;
exercise7();
return 0;
}
// ============================================================
// ANSWERS
// ============================================================
/*
Ex1:
class Heart { public: void beat() { cout << "Beating" << endl; } };
class Brain { public: void process() { cout << "Thinking" << endl; } };
class Human {
Heart heart; Brain brain; string name;
public:
Human(const string& n) : name(n) {}
void pump() { heart.beat(); }
void think() { brain.process(); }
};
Ex2:
class Library {
string name;
vector<Book*> books;
public:
Library(const string& n) : name(n) {}
void addBook(Book* b) { books.push_back(b); }
};
Ex5:
class CPU { public: void compute() { cout << "Computing" << endl; } };
class RAM { public: void store() { cout << "Storing" << endl; } };
class GPU { public: void render() { cout << "Rendering" << endl; } };
class Computer {
unique_ptr<CPU> cpu = make_unique<CPU>();
unique_ptr<RAM> ram = make_unique<RAM>();
unique_ptr<GPU> gpu = make_unique<GPU>();
public:
void run() { cpu->compute(); ram->store(); gpu->render(); }
};
Ex6:
class Logger { public: void log(const string& m) { cout << m << endl; } };
class GoodService {
Logger logger; // Composition instead of inheritance
public:
void doWork() { logger.log("Working..."); }
};
*/