Inheritance and virtual functions in C++
How virtual dispatch decides which function runs, why base classes need virtual destructors, and how overloading resolves.
Output questions on inheritance usually turn on a single keyword: virtual. Knowing exactly what it changes, along with how overloading and const work, lets you answer these questions with confidence.
Static versus dynamic binding
When you call a member function through a base pointer or reference, a non-virtual function is chosen from the declared type at compile time. A virtual function is chosen from the actual object's type at runtime.
class Shape {
public:
virtual void draw() const { cout << "Shape\n"; }
void name() const { cout << "shape\n"; }
virtual ~Shape() = default;
};
class Circle : public Shape {
public:
void draw() const override { cout << "Circle\n"; }
void name() const { cout << "circle\n"; }
};
Shape* s = new Circle();
s->draw(); // Circle (virtual)
s->name(); // shape (not virtual)
delete s;
Write override on every overriding function. If the signature does not match, for example because const is missing, the compiler reports an error instead of silently creating a new function.
Virtual destructors and abstract classes
Deleting a derived object through a base pointer when the base destructor is not virtual is undefined behaviour, and in practice the derived destructor usually never runs. Give any class meant for polymorphic use a virtual destructor. A class with at least one pure virtual function, written = 0, is abstract: you cannot create objects of it, only of derived classes that implement every pure virtual function.
Overloading and const
Overloaded functions share a name but differ in their parameters. The compiler picks the best match, preferring an exact match, then a promotion such as char to int, then a conversion such as int to double.
void print(int) { cout << "int\n"; }
void print(double) { cout << "double\n"; }
print('x'); // int: char is promoted to int
print(2.5f); // double: float is promoted to double
A const member function promises not to change the object. Only const member functions can be called on a const object or through a const reference.
Checklist for inheritance snippets
- Is the function virtual in the base class?
- What is the pointer type, and what is the object type?
- Does the derived signature match exactly, including const?
- Is the destructor virtual if the object is deleted through a base pointer?
More in Programming