Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple inheritance + virtual function mess

I have a diamond multiple inheritance scenario like this:

    A
  /   \
 B     C
  \   /
    D

The common parent, A, defines a virtual function fn().
Is it possible for both B and C to define fn()?
If it is, then the next question is - can D access both B and C's fn() without disambiguation? I'm assuming there is some syntax for this..
And is it possible for D to do that without knowing specifically who are B and C? B and C can be replaces by some other classes and I want the code in D to be generic.

What I'm trying to do is to have D somehow enumerate all of the instances of fn() it has in its ancestry. Is this possible in some other means that virtual functions?

like image 773
shoosh Avatar asked Mar 05 '09 19:03

shoosh


People also ask

Can multiple inheritance have virtual function?

Virtual inheritance is used when we are dealing with multiple inheritance but want to prevent multiple instances of same class appearing in inheritance hierarchy. From above example we can see that “A” is inherited two times in D means an object of class “D” will contain two attributes of “a” (D::C::a and D::B::a).

What is the main problem with multiple inheritance?

Multiple inheritance has been a controversial issue for many years, with opponents pointing to its increased complexity and ambiguity in situations such as the "diamond problem", where it may be ambiguous as to which parent class a particular feature is inherited from if more than one parent class implements said ...

Why should we avoid multiple inheritance?

Multiple inheritance in languages with C++/Java style constructors exacerbates the inheritance problem of constructors and constructor chaining, thereby creating maintenance and extensibility problems in these languages.

Why virtual classes are important in the case of multiple inheritance?

Virtual base classes offer a way to save space and avoid ambiguities in class hierarchies that use multiple inheritances. When a base class is specified as a virtual base, it can act as an indirect base more than once without duplication of its data members.


1 Answers

Unless you overwrite fn again in D, no it is not possible. Because there is no final overrider in a D object: Both C and B override A::fn. You have several options:

  • Drop either C::fn or B::fn. Then, the one that still overrides A::fn has the final overrider.
  • Place a final overrider in D. Then, that one overrides A::fn aswell as fn in C and B.

For example the following results in a compile time error:

#include <iostream>

class A {
public:
    virtual void fn() { }
};

class B : public virtual A {
public:
    virtual void fn() { }
};

class C : public virtual A {
public:
    virtual void fn() { }
};

// does not override fn!!
class D : public B, public C {
public:
    virtual void doit() {
        B::fn();
        C::fn();
    }
};

int main(int argc, char **argv) {
  D d;
  d.doit();
  return 0;
}

You can, however derive non-virtual from A in C and B, but then you have no diamond inheritance anymore. That is, each data-member in A appears twice in B and C because you have two A base-class sub-objects in an D object. I would recommend you to rethink that design. Try to eliminate double-objects like that that require virtual inheritance. It often cause such kind of conflicting situations.

A case very similar to this is when you want to override a specific function. Imagine you have a virtual function with the same name in B and C (now without a common base A). And in D you want to override each function but give different behavior to each. Depending whether you call the function with a B pointer or C pointer, you have the different behavior. Multiple Inheritance Part III by Herb Sutter describes a good way of doing that. It might help you decide on your design.

like image 175
Johannes Schaub - litb Avatar answered Sep 28 '22 12:09

Johannes Schaub - litb