Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple inheritance to solve abstract classes

Say I have 4 classes:

class I { public: virtual void X() = 0; };
class A : public virtual I { public: virtual void X() { } };
class B : public I {  };
class C : public A, public B { };

I, B and C are abstract, where as A is not. If I simply add virtual to the inheritance of I for B, then A::X() resolves I::X() in C.

However, I cannot change the source of B.

My question: Can I get A::X() to resolve I::X for C without being able to change B? I have tried declaring A and B to be virtual to C to no avail. I am trying to have no redundant code (e.g. have C declare X() { A::X(); }). Any neat hacks?

Also - there are a few questions very much like this, but I couldn't find any talking about using virtual inheritance. Please point to me one if I missed it.

like image 277
payo Avatar asked Jul 06 '12 17:07

payo


People also ask

Can we use multiple inheritance in abstract class?

Multiple inheritance Inheritance is another feature of object-oriented programming where a particular class can derive from a base class. Multiple inheritance allows the extension of more than one base class in a derived class. Abstract classes do not support multiple inheritance.

Can abstract class have multiple inheritance in java?

A class can extend at most one abstract class, but may implement many interfaces. That is, Java supports a limited form of multiple inheritance.

Why multiple inheritance is not allowed through abstract classes but is only allowed through interfaces?

As we have explained in the inheritance chapter, multiple inheritance is not supported in the case of class because of ambiguity. However, it is supported in case of an interface because there is no ambiguity. It is because its implementation is provided by the implementation class.


2 Answers

Your problem is with the vtables. In your current code, you have two of them - one in A's I and one in B's I. As long as only A virtually inherits I, you could just as well use regular inheritance and save the overhead. If both virtually inherited I you'd have only one instance of I in C, therefore only one vtable, and A::X could indeed cover the pure virual I::X.

Given you can't change B, the only place you can take care of both vtables is C. In my opinion, the way to go is what you mention - just have C::X forward the call to A::X. There's no code duplication there, and it makes C non-abstract:

class C : public A, public B {
public:
    virtual void X() { A::X(); }
};

As for virtual inheritance, there definitively have been some here. But you're welcome to ask...

like image 186
eran Avatar answered Sep 28 '22 04:09

eran


This is quite good: When virtual inheritance IS a good design?

The problem here is that in C you have two interfaces I. That is why A::x() satisfies its interface I - but it cannot make not abstract interface I from class B. For C the only way to have exactly one interface of I - is to change B to derive from I virtually - in this way both I interfaces from A and from B will be merged to one in C. You cannot change B - so the only way is to add this redundant code which you are trying to avoid. I mean define C::X().

like image 26
PiotrNycz Avatar answered Sep 28 '22 04:09

PiotrNycz