0

I have the following problem with inheritance (I would love to google it, but don't know the correct keywords it seems).

I have a Module class that implements IModule interface with function A(). I also have ClientModule class that inherits Module class and implements IClientModule interface with function B() that inherits IModule interface. This is where I am starting to get ambiguity and double inheritance problems.

Here is the class diagram that should tell a bit more about the problem:

enter image description here

I need to have separated access to Module class with IModule interface and ClientModule with IClientModule interface that offers access to IModule interface as well.

krizajb
  • 1,715
  • 3
  • 30
  • 43

2 Answers2

3

You are running into the "diamond inheritance" problem. Diamond inheritance has been discussed many times at this site and elsewhere. Make the inheritance of class Module and class IClientModule from class IModule virtual. This is not a perfect solution; sometimes the magic works, sometimes it doesn't. Where it doesn't work it's usually a case of demanding too much from inheritance.

David Hammen
  • 32,454
  • 9
  • 60
  • 108
  • In general, diamond inheritance should be avoided. Sometimes it cannot, but here he specifies everything from the start, so the solution should probably be to decompose the problem differently... – Wilbert May 21 '13 at 11:22
  • Does his situation really configure the diamond "problem"? I mean, `IModule` has no state, so the possibility of having two instances of it would not cause any collateral effects. I was about to suggest the same thing before noticing that. – freitass May 21 '13 at 11:23
  • Yes, this is the diamond problem because `IModule` has a method `A`. If `IModule::A()` is defined (rather than pure virtual), there's a problem with calling `A()` in `ClientModule`. Which `A` should be called, `IModule::A()` or `Module::A()`? There's also a problem if `IModule::A()` is pure virtual. Now `ClientModule` needs to define a method `A` because it's required but not defined on the `IModule` / `IClientModule` side of the diamond. – David Hammen May 21 '13 at 11:29
  • Complies .. will execute in few minutes. – krizajb May 21 '13 at 11:31
1

Make IClientModule not inherit IModule (and probably rename it IClient). In ClientModule, just inherit from Module and implement IClient.

Or, an alternative solution written after reading your comments:

Make your ClientModule class inherit from IClientModule as in your example. However, instead of inheriting from Module, simply give ClientModule a member variable that is a Module, and forward the calls to this member where needed. Something like this:

class IModule { virtual void A() {} };
class Module : public IModule { ... };
class IClientModule : public IModule { virtual void B() {} };

class ClientModule : public IClientModule 
{
    // ...
    virtual void A() { _module.A(); }

private:
    Module _module;
};

However, it is likely still better to avoid mashing these together and use my original solution.

Wilbert
  • 7,251
  • 6
  • 51
  • 91
  • But I want IClientModule to inherit IModule, so i get full access with it (IModule and IClientModule) – krizajb May 21 '13 at 11:19
  • 1
    What does 'get full access with it' mean? If your class inherits from IModule and from IClient, you can call methods of both interfaces on your ClientModule instance. – Wilbert May 21 '13 at 11:21
  • I won't have access to IModule functions and IClientModule functions in the same interface which I need. – krizajb May 21 '13 at 11:29
  • I updated my answer with an alternative solution that would solve this problem. – Wilbert May 21 '13 at 11:33
  • 4
    @krizajB - In general it's a bad idea to design for derived class behaviors in a parent class. If the class `IClientModule` does not depend on any `IModule` functionality, making `IClientModule` derive from `IModule` is backhanded programming. Not a good idea. While virtual inheritance might solve your particular problem, following Wilbert's advice is oftentimes an even better advice. – David Hammen May 21 '13 at 11:34
  • This is what I had in mind .. but seemed to easy: "was thinking of adding access to IModule interface to IClientModule with getter function, but there must be a better way to solve this kind of problems" – krizajb May 21 '13 at 11:38
  • Don't give access to IModule using a getter. Forward the calls transparently. Don't expose implementation details. – Wilbert May 21 '13 at 11:41
  • Ye, your suggestion is way better, I understand it now .. ClientModule is Wrapper class of Module. Basiclly I learned a lot, had no clue virtual inheritance or solution to diamond problem is an issues. Will research a bit more later on :) – krizajb May 21 '13 at 11:49