ProgrammingC++ Developer, System Architect

What is polymorphism in C++ and how is it implemented in practice?

Pass interviews with Hintsage AI assistant

Answer.

Background:

Polymorphism became one of the key characteristics of object-oriented programming early in the development of C++. The goal is to allow objects to be accessed through a base interface, regardless of their specific type. This significantly enhances the expressiveness and flexibility of code.

Problem:

Without polymorphism, the code becomes inflexible: you have to explicitly identify object types, use switch/case, and perform manual type casting. This complicates maintenance and extensibility of applications—adding new types becomes costly or impossible without modifying existing code.

Solution:

In C++, polymorphism is achieved through the use of virtual functions. Classes declare virtual methods, which are implemented by their subclasses. The base class provides a common interface, while the actual actions depend on the actual type of the object that the pointer or reference refers to.

Code example:

#include <iostream> class Animal { public: virtual void speak() const { std::cout << "Some animal sound "; } virtual ~Animal() {} }; class Dog : public Animal { public: void speak() const override { std::cout << "Woof! "; } }; void makeSound(const Animal& a) { a.speak(); } int main() { Dog dog; makeSound(dog); // Outputs: Woof! }

Key features:

  • Virtual functions must be declared with the virtual keyword in the base class.
  • For safety, use a virtual destructor in a polymorphic hierarchy.
  • To explicitly override, use override—this enhances code safety.

Trick Questions.

What happens if the base class destructor is not declared virtual?

Deleting an object through a pointer to the base class will only call the base class destructor, and the derived class destructor will not be called, leading to resource leaks.

Code example:

class Base { public: ~Base() { /*...*/ } }; class Derived : public Base { public: ~Derived() { /*...*/ } }; Base* obj = new Derived(); delete obj; // UB: Derived::~Derived will not be called

Is it possible to declare only some virtual methods and leave the destructor non-virtual?

No, if a class is polymorphic (has at least one virtual function), the destructor must be virtual to avoid memory or resource leaks.

Do virtual functions work for members declared as static?

No, static class members cannot be virtual because they do not belong to a specific object, and there is no dynamic binding mechanism for them.

Common Mistakes and Anti-Patterns

  • Lack of a virtual destructor in a hierarchy with virtual methods.
  • Forgetting to mark the override method in the child class, leading to incorrect method overriding.
  • Calling virtual functions from constructors/destructors, where dynamic binding should not occur.

Real-Life Example

Negative Case

A very large class hierarchy of devices, with each derived class managing its own resource (e.g., an open file), but the base class destructor is not virtual. When deleting through a base pointer, resources are not freed.

Pros: The project builds quickly, minimal virtual calls.

Cons: Memory leaks, improper destruction. Extremely difficult to maintain and extend.

Positive Case

A well-thought-out polymorphic hierarchy, where the base class has virtual functions and a virtual destructor. The override keyword is used and RAII principles are applied.

Pros: Safe resource handling, easy extension, testability.

Cons: Slightly lower performance due to vtable lookup, immunity to "over-engineering" when inheritance is applied unnecessarily.