问题
I have an abstract base class which acts as an interface.
I have two \"sets\" of derived classes, which implement half of the abstract class. ( one \"set\" defines the abstract virtual methods related to initialization, the other \"set\" defines those related to the actual \"work\". )
I then have derived classes which use multiple inheritance to construct fully defined classes ( and does not add anything itself ).
So: ( bad pseudocode )
class AbsBase {
virtual void init() = 0;
virtual void work() = 0;
}
class AbsInit : public AbsBase {
void init() { do_this(); }
// work() still abs
}
class AbsWork : public AbsBase {
void work() { do_this(); }
// init() still abs
}
class NotAbsTotal : public AbsInit, public AbsWork {
// Nothing, both should be defined
}
First of all, can I do this? Can I inherit from two classes which are both derived from the same Base? (I hope so).
Here is the \"real problem\", though (I lied a bit above to simplify the example).
What I have really gone and done is add non abstract accessors methods to the base class:
class AbsBase {
public:
void init() { init_impl(); }
void work() { work_impl(); }
private:
virtual void init_impl() = 0;
virtual void work_impl() = 0;
}
Because, a common idiom is to make all virtual methods private.
Unfortunately, now both AbsInit, and AbsWork inherit these methods, and so NotAbsTotal inherits \"two of each\" ( I realize I may be butchering what is really happening at compile time ).
Anyway, g++ complains that: \"request for member init() is ambiguous\" when trying to use the class.
I assume that, had I used my AbsBase class as a pure interface, this would have been avoided ( assuming that the top example is valid ).
So: - Am I way off with my implementation? - Is this a limitation of the idiom of making virtual methods private? - How do I refactor my code to do what I want? ( Provide one common interface, but allow a way to swap out implementations for \"sets\" of member functions )
Edit:
Seems I am not the first one: http://en.wikipedia.org/wiki/Diamond_problem
Seems Virtual Inheritance is the solution here. I have heard of virtual inheritance before, but I have not wrapped my head around it. I am still open to suggestions.
回答1:
It looks like you want to do virtual inheritance. Whether that turns out to actually be a good idea is another question, but here's how you do it:
class AbsBase {...};
class AbsInit: public virtual AbsBase {...};
class AbsWork: public virtual AbsBase {...};
class NotAbsTotal: public AbsInit, public AbsWork {...};
Basically, the default, non-virtual multiple inheritance will include a copy of each base class in the derived class, and includes all their methods. This is why you have two copies of AbsBase -- and the reason your method use is ambiguous is both sets of methods are loaded, so C++ has no way to know which copy to access!
Virtual inheritance condenses all references to a virtual base class into one datastructure. This should make the methods from the base class unambiguous again. However, note: if there is additional data in the two intermediate classes, there may be some small additional runtime overhead, to enable the code to find the shared virtual base class.
回答2:
You need to to declare the inheritance as virtual:
struct AbsBase {
virtual void init() = 0;
virtual void work() = 0;
};
struct AbsInit : virtual public AbsBase {
void init() { }
};
struct AbsWork : virtual public AbsBase {
void work() { }
};
struct NotAbsTotal : virtual public AbsInit, virtual public AbsWork {
};
void f(NotAbsTotal *p)
{
p->init();
}
NotAbsTotal x;
回答3:
It can be done, although it gives most the shivers.
You need to use "virtual inheritance", the syntax for which is something like
class AbsInit: public virtual AbsBase {...};
class AbsWork: public virtual AbsBase {...};
class NotAbsTotal: public AbsInit, public AbsWork {...};
Then you have to specify which function you want to use:
NotAbsTotal::work()
{
AbsInit::work_impl();
}
(UPDATED with correct syntax)
回答4:
You have to start thinking in the terms of what you are trying to model here.
Public inheritance should only ever be used to model an "isa" relationship, e.g. a dog is a animal, a square is a shape, etc.
Have a look at Scott Meyer's book Effective C++ for an excellent essay on what the various aspects of OO design should only ever be interpreted as.
Edit: I forgot to say that while the answers so far provided are technically correct I don't think any of them address the issues of what you are trying to model and that is the crux of your problem!
HTH
cheers,
Rob
回答5:
I found a good and simple example at the below link. The article explains with an example program for calculating the area and perimeter of a rectangle. You can check it..cheers
Multilevel Inheritance is an inheritance hierarchy wherein one derived class inherits from multiple Base Classes. Read more..
http://www.mobihackman.in/2013/09/multiple-inheritance-example.html
来源:https://stackoverflow.com/questions/254673/multiple-inheritance-from-two-derived-classes