Background of the question:
C++ introduced support for object-oriented programming, which is fundamental for modern languages. To implement polymorphism, virtual functions were used. This allowed the necessary implementation of a method to be called at runtime rather than just at compile time, which is critical for inheritance-based architecture.
Problem:
A common mistake is the confusion between static and dynamic method calls, forgotten virtual destructors, incorrect handling of inheritance (for example, object slicing, calling the base version instead of the override). Often misunderstood is when polymorphism is actually working.
Solution:
A virtual function is declared with the virtual keyword in the base class and can be overridden in the derived class. If a function is called through a pointer or reference to the base class, the version from the derived class will be executed.
Code example:
struct Base { virtual void foo() { std::cout << "Base::foo "; } }; struct Derived : Base { void foo() override { std::cout << "Derived::foo "; } }; void call(Base& b) { b.foo(); } int main() { Derived d; call(d); // Will output Derived::foo }
Key features:
Does polymorphism work when passing an object by value?
No. Passing by value leads to "slicing" — only the part corresponding to the parameter type (usually the base class) is copied, and polymorphism is disabled.
Code example:
void call(Base b) { b.foo(); } // always calls Base::foo
Is it necessary to declare the destructor virtual in the base class?
Yes, if deletion of derived objects through a pointer to the base class is expected. Otherwise, there will be a memory leak or resources will not be released.
Code example:
struct Base { virtual ~Base() {} };
What happens if the override keyword is not used in the derived class?
If the override is not specified in the derived class, but the function signature is incorrectly changed (for example, missing const or incorrect parameters), the function will not override the virtual one, a new one is created, and polymorphism will not work as expected.
The programmer did not declare the destructor of the base class as virtual; deleting an array of objects through a base pointer led to memory leaks.
Pros:
Cons:
A virtual destructor was declared; only references/pointers to the base type were used. Polymorphism worked correctly.
Pros:
Cons: