Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

hierarchical interfaces and implementations

The following code only works if you uncomment the line

  virtual void FuncA() { ImplA::FuncA(); }

in class ImplB, otherwise I get compiler error:

cannot instantiate abstract class ... FuncA(void)' : is abstract

Question is why doesn't it get the implement for FuncA() from the inherited ImplA?

class InterfaceA  {
public: 
  virtual void FuncA()=0;
};

class InterfaceB : public InterfaceA {
public: 
  virtual void FuncB()=0;
};

class ImplA : public InterfaceA  {
public: 
  virtual void FuncA() { printf("FuncA()\n"); }
};

class ImplB : public ImplA, public InterfaceB {
public: 
  // virtual void FuncA() { ImplA::FuncA(); }
  virtual void FuncB() { printf("FuncB()\n"); }
};

{
  ImplB *b = new ImplB();
  InterfaceA *A= b; 
  A->FuncA();
  InterfaceB *B= b;
  B->FuncB();
  B->FuncA();
}
like image 603
perry Avatar asked May 14 '16 23:05

perry


1 Answers

You've hit an instance of the "diamond" problem in multiple inheritance. You'll need to use "virtual" inheritance (which amounts to adding the keyword virtual when inheriting)

The problem is that ImplB has two paths to the base class InterfaceA. However, your intention is that the interfaces do not provide any implementation. Thus, you need to indicate this to the compiler, so it can unify the pure virtual functions.

For a much better explanation: http://www.cprogramming.com/tutorial/virtual_inheritance.html

I've modified your code to add virtual when you inherit from interfaces. Now it compiles, even with the line commented. Also note, I think you are missing virtual destructors, so you'll have some other problems down the line. This code compiles, without uncommenting FuncA.

#include <cstdio>

class InterfaceA  {
public: 
  virtual void FuncA()=0;
};

class InterfaceB : public virtual InterfaceA {
public: 
  virtual void FuncB()=0;
};

class ImplA : public virtual InterfaceA  {
public: 
  virtual void FuncA() { printf("FuncA()\n"); }
};

class ImplB : public ImplA, public virtual InterfaceB {
public: 
  // virtual void FuncA() { ImplA::FuncA(); }
  virtual void FuncB() { printf("FuncB()\n"); }
};

int main()
{
  ImplB *b = new ImplB();
  InterfaceA *A= b; 
  A->FuncA();
  InterfaceB *B= b;
  B->FuncB();
  B->FuncA();
}
like image 94
eyeApps LLC Avatar answered Oct 08 '22 23:10

eyeApps LLC