How to properly implement polymorphism with base class pointers in C++?

How to properly implement polymorphism with base class pointers in C++?

I'm learning Object-Oriented Programming in C++ and trying to understand polymorphism with base class pointers.

I created a base class Animal and a derived class Dog, both with a speak() method. I expected that when I create a pointer of type Animal* and assign it to a Dog object, calling speak() would execute the Dog version. However, it always calls the base class version.

How can I achieve that ?

#include <iostream>
using namespace std;

class Animal {
public:
    void speak() {
        cout << "Animal sound" << endl;
    }
};

class Dog : public Animal {
public:
    void speak() {
        cout << "Woof!" << endl;
    }
};

int main() {
    Animal* a = new Dog();
    a->speak();  // Expected: Woof!, Actual: Animal sound
    return 0;
}

Answer

You seem to expect that the method that is called will be determined on the actual runtime type of the object it is used with (here a Dog).

This is called runtime dispatch and it is done in C++ only for virtual methods.

For method which are not virtual the call is determined at compile time, based on the type of the pointer (in your case Animal*) and not the actual object it points to.

A fixed version:

#include <iostream>

class Animal {
public:
//--vvvvvvv---------------
    virtual void speak() {
        std::cout << "Animal sound" << std::endl;
    }
};

class Dog : public Animal {
public:
//---------------vvvvvvvv--
    void speak() override {
        std::cout << "Woof!" << std::endl;
    }
};

int main() {
    Animal* a = new Dog();
    a->speak(); 
}

Output:

Woof!

Live demo - Godbolt

Note:
I also used the override specifier in the derived class which is recommended, in order to get the help of the compiler when you attempt to override a method that is not eligable for that. But stricktly it not a must (it is enough that the base method is marked virtual).

A side note:
It is recommended to avoid using namespace std;. See: What's the problem with "using namespace std;"?.

Enjoyed this question?

Check out more content on our blog or follow us on social media.

Browse more questions