Multiple Inheritance with abstract and defined inh

2019-06-26 05:02发布

问题:

First off I apologize if there is another post out there that answers this, all the similar posts I found dealt with diamond inheritance schemes or defined functions, which this does not.

In short, I'm wondering if it is possible to have one class inherit from two other classes where both child classes has a function with the same name and arguments but it is defined in one child class, and pure-virtual in another. Furthermore if I can do this, would invoking the function on the pure-virtual/abstract class end up calling the defined function on the other child class with minimal changes to the derived class?

Example:

class A
{
    public:
    virtual void Set(int X) = 0;
};

class B
{
    public:
    virtual void Set(int X);
};

class AB : public A, public B
{
    //other methods not relevant to example go here
};

int main(int argc, char **argv)
{
    int Y = 5;
    A* ObjectA = new AB();
    ObjectA->Set(Y);
    return 0;
}

So far my attempts to compile this basic example have been met with errors that say:

'AB' : cannot instantiate abstract class due to following members: 'void A::Set(int)' : is abstract

When doing my own research I couldn't find a clear answer, but based on other questions that dealt with related topics I found that using a "using B::Set" in class AB may help with this. But when I try adding it to the AB class definition, the error persists.

Is there any way I can make this work?

回答1:

Have you tried implementing the method:

class AB : public A, public B
{
    void Set(int X) {}
};

The reason it's not working is that A::Set() is pure virtual. I.e. it has no implementation. But you try to call it. You have to override it in the derived class in order to be able to instantiate the derived class.

The using doesn't work in your case because you have an A*, so there's no ambiguity for the compiler.

In case you had:

AB* ObjectA = new AB();
ObjectA->Set(Y);

you'd have to use using inside the declaration of AB to resolve the ambiguity.



回答2:

If you had 2 normal functions Set in A and B, then using B::Set would tell the compiler that if you have object of class AB and call method Set of that object, B::Set will be invoked, if AB::Set not defined explicitly.

Your situation is different. You have pure virtual function A::Set that leads A to be abstract class. As AB does not override A::Set, AB becomes abstract too, that is why you cannot instantiate it.

What you can do here

You can implement AB::set to call B::Set:

class AB : public A, public B
{
public:
    void Set(int x) { return B::Set(x); }
};

Also I do not recommend same method names for base classes, as I do not recommend multiple inheritance, try use aggregation instead.



回答3:

Class AB derives from A, A has a pure virtual method making the class abstract, AB must implement any pure virtual methods declared in a base class in order to be instantiated.

I would try to avoid multiple inheritance it can cause many headaches and there are generally better ways to solve a problem, for instance in this example I don't understand the point in deriving from both A and B, if B shares and in fact implements the same interface as A then surely B should be derived from A.