cpp

exercises

exercises.cpp⚙️
/**
 * Virtual Inheritance - Exercises
 * Compile: g++ -std=c++17 -Wall exercises.cpp -o exercises
 */

#include <iostream>
#include <string>
using namespace std;

// ============================================================
// Exercise 1: Fix the Diamond ⭐
// ============================================================

// TODO: Fix using virtual inheritance
class Person {
public:
    string name;
    Person(const string& n = "") : name(n) {}
};

class Student : public Person {  // Add virtual
public:
    int studentId;
    Student(const string& n = "", int id = 0) : Person(n), studentId(id) {}
};

class Employee : public Person {  // Add virtual
public:
    int employeeId;
    Employee(const string& n = "", int id = 0) : Person(n), employeeId(id) {}
};

class TeachingAssistant : public Student, public Employee {
public:
    TeachingAssistant(const string& n, int sid, int eid)
        : Student(n, sid), Employee(n, eid) {}  // Fix constructor
};

void exercise1() {
    TeachingAssistant ta("Alice", 1001, 2001);
    // cout << ta.name << endl;  // Should work without ambiguity
    cout << "(Fix diamond problem)" << endl;
}

// ============================================================
// Exercise 2: Constructor Order ⭐⭐
// ============================================================

// Predict and verify the constructor order

class A {
public:
    A() { cout << "A "; }
};

class B : virtual public A {
public:
    B() { cout << "B "; }
};

class C : virtual public A {
public:
    C() { cout << "C "; }
};

class D : public B, public C {
public:
    D() { cout << "D "; }
};

void exercise2() {
    cout << "Constructor order: ";
    D d;
    cout << endl;
    // What is the output?
}

// ============================================================
// Exercise 3: Initialize Virtual Base ⭐⭐
// ============================================================

class Device {
protected:
    string model;
public:
    Device(const string& m) : model(m) {
        cout << "  Device(" << m << ")" << endl;
    }
};

class Phone : virtual public Device {
public:
    Phone() : Device("DefaultPhone") {
        cout << "  Phone()" << endl;
    }
};

class Camera : virtual public Device {
public:
    Camera() : Device("DefaultCamera") {
        cout << "  Camera()" << endl;
    }
};

// TODO: Create Smartphone that properly initializes Device with "Smartphone"
class Smartphone : public Phone, public Camera {
public:
    // ⚠️ LEARNING NOTE: With virtual inheritance, the MOST DERIVED class
    // must call the virtual base constructor directly!
    // 
    // Why? Because Device is shared (virtual), if Phone and Camera both
    // tried to initialize it, we'd have a conflict. So C++ requires the
    // final derived class (Smartphone) to do it.
    //
    // FIX: Add Device("Smartphone") to the initializer list
    Smartphone() : Device("Smartphone") {
        cout << "  Smartphone()" << endl;
    }
};

void exercise3() {
    cout << "Creating Smartphone:" << endl;
    Smartphone s;
    // Should print "Device(Smartphone)" not "Device(DefaultPhone)"
}

// ============================================================
// Exercise 4: Interface Hierarchy ⭐⭐⭐
// ============================================================

// TODO: Create interface hierarchy using virtual inheritance
// IEntity (base with id)
//   ├── IMoveable (with move())
//   └── IDrawable (with draw())
// GameObject implements both

void exercise4() {
    // GameObject obj(1);
    // obj.move(10, 20);
    // obj.draw();
    // cout << "ID: " << obj.getId() << endl;
    cout << "(Create interface hierarchy)" << endl;
}

// ============================================================
// Exercise 5: Mixin Pattern ⭐⭐⭐
// ============================================================

// Use virtual inheritance for mixins

class Named {
protected:
    string name_;
public:
    Named(const string& n = "") : name_(n) {}
    string getName() const { return name_; }
};

// TODO: Create mixins that virtually inherit from Named
// - Printable (adds print())
// - Saveable (adds save())
// - Document that combines both

void exercise5() {
    // Document doc("Report");
    // doc.print();
    // doc.save();
    cout << "(Implement mixin pattern)" << endl;
}

// ============================================================
// MAIN
// ============================================================

int main() {
    cout << "=== Virtual Inheritance Exercises ===" << endl;
    
    cout << "\nEx1: Fix Diamond" << endl;
    exercise1();
    
    cout << "\nEx2: Constructor Order" << endl;
    exercise2();
    
    cout << "\nEx3: Initialize Virtual Base" << endl;
    exercise3();
    
    cout << "\nEx4: Interface Hierarchy" << endl;
    exercise4();
    
    cout << "\nEx5: Mixin Pattern" << endl;
    exercise5();
    
    return 0;
}

// ============================================================
// ANSWERS
// ============================================================
/*
Ex1:
class Student : virtual public Person { ... };
class Employee : virtual public Person { ... };
class TeachingAssistant : public Student, public Employee {
    TeachingAssistant(const string& n, int sid, int eid)
        : Person(n), Student(n, sid), Employee(n, eid) {}
};

Ex2: Output is "A B C D"
- Virtual base A constructed first (once)
- Then B, C in declaration order
- Finally D

Ex3:
class Smartphone : public Phone, public Camera {
public:
    Smartphone() : Device("Smartphone"), Phone(), Camera() {
        cout << "  Smartphone()" << endl;
    }
};

Ex4:
class IEntity { 
    int id;
public:
    IEntity(int i) : id(i) {}
    int getId() const { return id; }
    virtual ~IEntity() = default;
};
class IMoveable : virtual public IEntity {
public:
    virtual void move(int x, int y) = 0;
};
class IDrawable : virtual public IEntity {
public:
    virtual void draw() = 0;
};
class GameObject : public IMoveable, public IDrawable {
public:
    GameObject(int id) : IEntity(id) {}
    void move(int x, int y) override { cout << "Moving to " << x << "," << y << endl; }
    void draw() override { cout << "Drawing" << endl; }
};

Ex5:
class Printable : virtual public Named {
public:
    void print() { cout << "Printing: " << name_ << endl; }
};
class Saveable : virtual public Named {
public:
    void save() { cout << "Saving: " << name_ << endl; }
};
class Document : public Printable, public Saveable {
public:
    Document(const string& n) : Named(n) {}
};
*/
Exercises - C++ Tutorial | DeepML