Skip to content

Teaching Notes: Module 04

  • Virtual functions and polymorphism
  • Virtual destructors
  • Abstract classes
  • Interfaces (pure abstract classes)
  • Deep copy with dynamic memory

const Animal* pet = new Dog();
pet->makeSound(); // Without virtual: "Generic animal sound"
// With virtual: "Woof!"
  1. Forgetting virtual keyword

    class Animal {
    public:
    void makeSound(); // NOT polymorphic
    virtual void makeSound(); // Polymorphic
    };
  2. Not testing with base pointer

    • The whole point is treating Dog/Cat as Animal

Create identical classes without virtual to show the difference.


Dog and Cat have Brain* - must deep copy!

  1. Shallow copy (DEFAULT)

    // Default copy: both point to SAME Brain!
    Dog original;
    Dog copy = original; // DISASTER
  2. Forgetting virtual destructor

    const Animal* pet = new Dog();
    delete pet; // Without virtual ~Animal(): Dog's Brain leaks!
  3. Not deleting old Brain in assignment

    Dog& Dog::operator=(const Dog& other) {
    if (this != &other) {
    delete _brain; // Free old!
    _brain = new Brain(*other._brain); // Deep copy
    }
    return *this;
    }
Dog a;
Dog b = a;
// Modify a's brain
a.getBrain()->ideas[0] = "Different idea";
// b's brain should NOT change

class Animal {
public:
virtual void makeSound() const = 0; // = 0 makes it pure virtual
};
Animal a; // ERROR: Animal is abstract
Animal* p = new Dog(); // OK
  • “Generic animal sound” makes no sense
  • Force derived classes to implement

class ICharacter {
public:
virtual ~ICharacter() {}
virtual std::string const& getName() const = 0;
virtual void equip(AMateria* m) = 0;
virtual void unequip(int idx) = 0;
virtual void use(int idx, ICharacter& target) = 0;
};
class AMateria {
public:
virtual AMateria* clone() const = 0;
};
class Ice : public AMateria {
public:
AMateria* clone() const {
return new Ice(*this);
}
};
  1. unequip() must NOT delete

    void Character::unequip(int idx) {
    // Save pointer before NULLing!
    // Subject says: handle dropped materias as you like
    _inventory[idx] = NULL;
    }
  2. MateriaSource memory

    • learnMateria takes ownership OR copies
    • createMateria returns new instance (caller owns)
  • “What’s the difference between AMateria and ICharacter?”
  • “Who owns the Materia after equip()? After unequip()?”
  • “Why do we need clone()?”