8

I am trying to figure out an interesting multiple inheritance issue.

The grandparent is an interface class with multiple methods:

class A
{
public:
    virtual int foo() = 0;
    virtual int bar() = 0;
};

Then there are abstract classes that are partially completing this interface.

class B : public A
{
public:
    int foo() { return 0;}
};

class C : public A
{
public:
    int bar() { return 1;}
};

The class I want to use inherits from both of the parents and specifies what method should come from where via using directives:

class D : public B, public C
{
public:
    using B::foo;
    using C::bar;
};

When I try to instantiate a D I get errors for trying to instantiate an abstract class.

int main()
{
    D d; //<-- Error cannot instantiate abstract class.

    int test = d.foo();
    int test2 = d.bar();

    return 0;
}

Can someone help me understand the problem and how to best make use of partial implementations?

Eric Pi
  • 1,904
  • 12
  • 13
Michael
  • 93
  • 5
  • 2
    In a diamond pattern you need to use virtual inheritance. But I don't believe that's going to fix your problem by itself. – David May 03 '11 at 02:35

2 Answers2

13

You don't have diamond inheritance. The B and C base classes of D each have their own A base class subobject because they do not inherit virtually from A.

So, in D, there are really four pure virtual member functions that need to be implemented: the A::foo and A::bar from B and the A::foo and A::bar from C.

You probably want to use virtual inheritance. The class declarations and base class lists would look like so:

class A
class B : public virtual A
class C : public virtual A
class D : public B, public C

If you don't want to use virtual inheritance then you need to override the other two pure virtual functions in D:

class D : public B, public C
{
public:
    using B::foo;
    using C::bar;

    int B::bar() { return 0; }
    int C::foo() { return 0; }
};
James McNellis
  • 348,265
  • 75
  • 913
  • 977
-2

You need to make your base classes virtual in order for them to inherit properly. The general rule is that all non-private member functions and base classes should be virtual UNLESS you know what you're doing and want to disable normal inheritance for that member/base.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • 1
    "The general rule is that all public member functions and base classes should be virtual" What? Whose general rule is that? If anything, the general rule concerning virtual member functions is to make them private and have a public nonvirtual member function in the base class call the private virtual member function (this is discussed in the GotW article ["Virtuality"](http://www.gotw.ca/publications/mill18.htm)). As for virtual base classes... I can only think of one case in the last few years that I've needed to use virtual inheritance. – James McNellis May 03 '11 at 02:38
  • @JamesMcNellis "_I can only think of one case in the last few years that I've needed to use virtual inheritance._" How many times did you _needed_ to use **non**-virtual inheritance? – curiousguy Nov 19 '11 at 05:50
  • @JamesMcNellis: That article is mostly total BS. About the only thing it gets right is that most member functions (virtual or not) should be private. Having public non-virtual member functions is a disaster waiting to happen and basically means that the class cannot be subclassed. – Chris Dodd Aug 03 '12 at 18:50
  • @ChrisDodd What are you talking about... dude, if you say what you personally think, at least don't pretend what you're saying is a fact... [gtkmm](http://www.gtkmm.org/en/) is just one of many examples to C++ classes where there are just a few virtual functions, usually protected, and the classes are still fully meant to be subclassed (and they *are* subclassed very easily). If you prefer to have all your public methods virtual - that's fine. I don't like it, but I won't tell you how to write code. Just don't pass personal habits to other people as if they were facts... – cfa45ca55111016ee9269f0a52e771 Feb 16 '13 at 15:44