Polymorphism: virtual and override

Overriding a method

Every animal makes a sound, but each kind makes a different one. The parent says “animals can speak” with a virtual method, and each child overrides it with its own version:

#include <iostream>
using namespace std;

class Animal {
public:
    virtual void speak() const {
        cout << "...\n";
    }
    virtual ~Animal() {}
};

class Dog : public Animal {
public:
    void speak() const override {
        cout << "Woof!\n";
    }
};

class Cat : public Animal {
public:
    void speak() const override {
        cout << "Meow!\n";
    }
};

int main() {
    Dog d;
    Cat c;
    d.speak();
    c.speak();
    return 0;
}

Output

Woof!
Meow!

The magic: one pointer, many shapes

Polymorphism (Greek for “many shapes”) means a pointer or reference to the parent can point at any child, and calling a virtual method runs the child's version:

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

class Animal {
public:
    virtual void speak() const { cout << "...\n"; }
    virtual ~Animal() {}
};

class Dog : public Animal {
public:
    void speak() const override { cout << "Woof!\n"; }
};

class Cow : public Animal {
public:
    void speak() const override { cout << "Moo!\n"; }
};

void makeItSpeak(const Animal& a) {
    a.speak();                 // which speak()? depends on the real object
}

int main() {
    Dog d;
    Cow c;
    makeItSpeak(d);
    makeItSpeak(c);

    vector<Animal*> farm = {&d, &c, &d};
    for (Animal* a : farm) {
        a->speak();
    }
    return 0;
}

Output

Woof!
Moo!
Woof!
Moo!
Woof!

Think of it like this: A TV remote has one “power” button, but it works on any brand of TV. You don't care what's inside the TV – you press the same button and each TV does its own thing.

  • virtual in the parent says “children may replace this”.
  • override in the child says “I'm replacing the parent's version”. The compiler checks you got the name and parameters right.
  • virtual ~Animal() {} is a virtual destructor. Always add one to a class that has virtual methods, so objects are cleaned up correctly.

Common mistake: Without virtual in the parent, a.speak() would always run the parent's version and print ..., even for a Dog.

HOME LABS COMMUNITY DASHBOARD