How do virtual functions work with multiple inheritance in C++?

If a class inherits from multiple base classes that have virtual functions, how are the virtual function calls resolved?

When a class inherits from multiple base classes that have virtual functions, the virtual function calls are resolved based on the order of inheritance and the specific class hierarchy.

In C++, when a class inherits from multiple base classes, it can potentially inherit multiple implementations of the same virtual function. To resolve this ambiguity, the compiler uses a mechanism called "virtual function table" (vtable) for each class.

Each class that contains virtual functions has its own vtable, which is an array of function pointers. The vtable contains entries for all the virtual functions declared in the class and its base classes. When a class inherits from multiple base classes, its vtable is constructed by concatenating the vtables of its base classes.

Here's an example to illustrate how virtual function calls are resolved in multiple inheritance:

#include <iostream>

class BaseA {
public:
  virtual void foo() {
    std::cout << "BaseA::foo()\n"; }
};

class BaseB {
public:
  virtual void foo() {
    std::cout << "BaseB::foo()\n"; }
  virtual void bar() {
    std::cout << "BaseB::bar()\n"; }
};

class Derived : public BaseA, public BaseB {
public:
  void foo() override {
    std::cout << "Derived::foo()\n"; }
};

int main() {
  Derived derived;
  BaseA* baseA = &derived;
  BaseB* baseB = &derived;

  baseA->foo();
  baseB->foo();
  baseB->bar();
}
Derived::foo()
Derived::foo()
BaseB::bar()

In this example, the Derived class inherits from both BaseA and BaseB. Both base classes have their own virtual function foo(), and BaseB also has a virtual function bar().

When baseA->foo() is called, the compiler looks up the vtable of BaseA and finds the entry for foo(). Since Derived overrides foo(), the Derived::foo() implementation is called.

Similarly, when baseB->foo() is called, the compiler looks up the vtable of BaseB and finds the entry for foo(). Again, since Derived overrides foo(), the Derived::foo() implementation is called.

When baseB->bar() is called, the compiler looks up the vtable of BaseB and finds the entry for bar(). Since Derived doesn't override bar(), the BaseB::bar() implementation is called.

It's important to note that if a derived class inherits from multiple base classes and does not override a virtual function that is present in multiple base classes, the compiler will generate an ambiguity error. To resolve this, you need to explicitly specify which base class's implementation should be used using scope resolution.

class Derived : public BaseA, public BaseB {
 public:
  void foo() override {
    // Explicitly call BaseA's implementation
    BaseA::foo();
  }
};

In summary, when a class inherits from multiple base classes with virtual functions, the virtual function calls are resolved based on the vtable and the specific class hierarchy. The derived class can override the virtual functions, and the most derived implementation will be called.

Run-time Polymorphism

Learn how to write flexible and extensible C++ code using polymorphism, virtual functions, and dynamic casting

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Why should I use a virtual destructor in C++?
I noticed in the lesson that a virtual destructor was used in a base class. Why is this necessary?
What is the performance impact of using virtual functions in C++?
The lesson mentions that using virtual functions has performance implications. Can you explain what those are?
What are pure virtual functions in C++?
I came across the term "pure virtual function" while learning about polymorphism. What does it mean and how is it used?
Can virtual functions have default implementations in C++?
Is it possible to provide a default implementation for a virtual function in a base class?
What is the performance impact of using dynamic_cast in C++?
The lesson mentions using dynamic_cast for downcasting. Is there any significant performance overhead associated with dynamic_cast?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant