0

In my C++ program, I have two classes (B1 and B2) with their own methods but 1 ("accidentally") in common. For example:

class B1 header:

void height();
void size();
void enabled();

class B2 header:

void width();
void length();
void enabled();

Now I have a class A that inherit from B1 and B2. Since I have a "conflict" in method enabled() after multiple inheritance, how can I avoid this? Is there a way to exclude a method from inheritance? For example I could exclude enabled() inheritance from class B1 (I cannot set it private since it's used from other classes derived from B1). Any other idea?

ABCplus
  • 3,981
  • 3
  • 27
  • 43
  • 1
    1) Don't do multiple inheritance 2) Don't name the methods the same. Also IIRC compiler warns you when there's an ambiguity. – m0skit0 Jul 01 '15 at 14:43
  • See:http://stackoverflow.com/questions/18398409/c-inherit-from-multiple-base-classes-with-the-same-virtual-function-name and http://stackoverflow.com/questions/2004820/inherit-interfaces-which-share-a-method-name – NathanOliver Jul 01 '15 at 14:45
  • @m0skit0: but suppose that class A should implement methods height(), size(), width() and length(). How can I avoid multiple inheritance? Moreover, different names (B1::enabled() and B2::isEnabled() for example) might be confusing. – ABCplus Jul 01 '15 at 14:46
  • You can always use interfaces (virtual methods) and compose instead of inherit, like Java/C# do. – m0skit0 Jul 01 '15 at 14:50
  • This is why multiple inheritance is discouraged, except for multiply inheriting/implementing 'interfaces' (totally abstract classes). You can almost certainly re-factor this problem out. One possibility may be that `A` should "wrap" an instance of both `B1` and `B2`. Ask yourself - is it really true that `A` "is a" `B1`, and `A` "is (also) a" `B2`?? – Grimm The Opiner Jul 01 '15 at 14:50
  • @GrimmTheOpiner: Basically I have choosen inheritance not because A "is a" B1 but because A needed all the methods of B, for example height(), setHeight(int height), checkHeight(int height), etc... So to do not redefine all the methods, I thought inheritance was not a bad idea in this case. This could end in an another SO question: could inheritance being used to avoid method redefine even if derived class has nothing to do with base? – ABCplus Jul 01 '15 at 15:00
  • @ABCplus well it's hard to say without seeing the complete picture but it's possible that classes `B1` and `B2` might best be merged. Between them they have attributes of `width`, `height`, `length`, `enabled`, and the rather generic `size`. Merge them into 1, keep three of the dimensions but drop `size`, and have one class with four properties instead of two classes with 3. – Grimm The Opiner Jul 02 '15 at 07:08

4 Answers4

5

You can solve the ambiguity but you will inherit both functions anyway. There is no way you can choose not to inherit some function. To fix the ambiguity use the following:

class B1
{
public:
    void height();
    void size();
    void enabled();
};

class B2
{
public:
    void width();
    void length();
    void enabled();
};

class A: public B1, public B2
{
public: 
    using B2::enabled;
};
ixSci
  • 13,100
  • 5
  • 45
  • 79
  • I didn't know `using` keyword – ABCplus Jul 01 '15 at 14:47
  • @ABCplus, in this case it "drags" `B2::enabled` to the `A` class making it the only candidate to consider on call with an A's object. It is always used in such contexts to solve the ambiguity. – ixSci Jul 01 '15 at 14:51
  • `using` works for c++11, if you do not have it you can define `A::enabled()` and call either `B1::enabled()` or `B2::enabled()` or both explicitly. – Slava Jul 01 '15 at 14:53
  • @Slava, this `using` has nothing to do with C++11. It is much older feature – ixSci Jul 01 '15 at 14:54
  • @ixSci hmm you are right, there is always something that I do not remember correctly :( – Slava Jul 01 '15 at 14:57
0

You can try using namespaces. Make B1::enabled() a member of namespace called X and B2::enabled() - Y. In the derived class use X::enabled() or Y::enabled().

ForceBru
  • 43,482
  • 10
  • 63
  • 98
0

You can disambiguate your calls to base class methods using the syntax Class::function. In your case, wherever you use enabled, qualify the call:

B1::enabled();
B2::enabled();

If you only need one of those functions, you can write a using-declaration:

using B1::enabled;
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
0

Personally I would encapsulate B in an A and provide an interface to anything useful it provides in A that you need outside of it, rather than inheriting. If you need polymorphic behaviour, make both A and B inherit from the same abstract interface.

Robinson
  • 9,666
  • 16
  • 71
  • 115