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!
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