简体   繁体   中英

Diamond inheritance and pure virtual functions

Imagine a standard diamond inheritance. Class A defines pure virtual function fx, class B defines implementation for fx, classes C and D do nothing with fx. When trying to call fx on instance of class D you'll get 'ambiguous function call' error although there is only one implementation of fx. This can be solved by B and C inheriting from A in virtual manner. Is it a correct solution for the problem? How exactly does virtual inheritance handle merging of virtual function tables?

A--->B--->D

\\--->C------^

... Note, Herb Sutter wrote 3 excellent articles about multiple inheritance (1) here , (2) here and (3) here . He wrote a whole other bunch of useful articles in guru-of-the-week here . Highly recommended ...

First, i'm not sure that i get your hierarchy right. I take it it is like this:

struct A {
    virtual void F() = 0;
};

struct B : A { void F() { } };
struct C : A { };
struct D : B, C { };

Well, D is abstract, because there are two A subobjects in an object of type D: One that is made concrete by B through the lattice of B, and one that is still abstract in the lattice going through C . I take it you have a pointer to D and try to call F . Yes, an ambiguity arises, because the compiler finds two functions F in two separate lattices:

D -> B::F
D -> C -> A::F

Looking like this:

    F()   F()
     A     A
     |     |
 F() B     C
      \   /
        D 

You can fix that situation formally by deriving from A virtually:

struct B : virtual A { void F() { } };
struct C : virtual A { };
struct D : B, C { };

You then have this situation, called diamond inheritance:

       F()  
        A
      /   \
 F() B     C
      \   /
        D 

And doing the lookup, it finds that there is B::F overriding A::F . Although A::F can still be reached through D::C::A , that is not an ambiguity anymore, because A was inherited virtual.

Whether this is the correct solution in your particular problem - that's of course not certain. There are most often better ways than deriving virtual from a class. To your question about merging of virtual function tables - that's completely depending on the implementation. GCC , as far as i know, will keep a pointer to the one A instance in the virtual table of D , if we derive virtual.

Is it a correct solution for the problem?

"Diamond" inheritance is problematic, and the correct explanation of the solution takes a bit of explaining. I recommend you read the following chapters of Meyers' Effective C++ :

  • Item 26, Guard against potential ambiguity
  • Item 43, Use multiple inheritance judiciously .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM