0

I have the following interface A:

class A
{
    virtual void f() = 0;
}

I also have interfaces B, C that are derived from A:

class B : public A
{
    ...
}

class C : public A
{
    ...
}

class X implements B and Y implements C. also both of them are derived from class D

class X : public D, public B {...}
class Y : public D, public C {...}

Both of these classes have the same implementation of A::f() so i moved this implementation to D. Now when i try to instantiate X or Y, i get an error that f() is not implemented for them.

It seems that although the same method is implemented in the base class, the compiler does not recognise it as an implementation of the pure virtual function. What should i do?

Erik Sapir
  • 23,209
  • 28
  • 81
  • 141

5 Answers5

1

Implementation of D::f() knows nothing about A::f(). You have to either derive D from A (and B & C from D) or implement f() in both X and Y. The implementation can be quite trivial - just the call of the function in D (but don't call it D::f() then to avoid ambiguity).

Edit: (add info)

Still, if you can move this function between classes that freely, I', pretty unsure it has to even be the method, not some helper function.

qwm
  • 1,005
  • 8
  • 10
  • This is pretty much what i am doing now - i implemented the methods in D and the implementations of B,C simply call to D::f() – Erik Sapir Jan 18 '14 at 12:32
1

This is what you have to do:

class A { virtual void f( ) = 0; };

class B : virtual public A{};
class C : virtual public A{};
class D : virtual public A { void f(){} };

class X : public D, public B {  };
class Y : public D, public C {  };

The key here is that all classes are derived virtual from A. If you omit that virtual, X ends up with two instances of A, one inherited from D and one from B, and of course both must have implementations. This virtual ensures there is only one instance of A in the end, and the one implementation in D is sufficient.

pentadecagon
  • 4,717
  • 2
  • 18
  • 26
0

The function D::f() cannot be used to resolve the need to implement the pure virtual A::f() if class D does not derive from class A. What you get is a conflict instead of a resolution to the problem. On the other hand, if class D does derive from class A, you can do this. However,

  • The inheritance now has to be virtual.
  • This solution invokes the dreaded diamond inheritance. Caveat emptor.
David Hammen
  • 32,454
  • 9
  • 60
  • 108
0

I know this is not the answer but more of a workaround or a hack. Something like this:

template<class Parent>
class D : public Parent {
   static_assert(std::is_base_of<A,Parent>::value, "Not derived from A");
public:
   void f() { /*whatever you want here */ }
};

class X : public D<B> {
public:

};

class Y : public D<C> {
public:
};

I usually avoid multiple inheritance unless they are interfaces. Like how its used in Java or PHP.

[EDIT] Result: http://ideone.com/OtTZfh

Gasim
  • 7,615
  • 14
  • 64
  • 131
0

Instead of moving the implementation of f up the inheritance hierarchy, I would move it down by introducing a new common-base class for B and C:

class Common : public A {
  void f() override { /* ... */ }
};

class B : public Common {};
class C : public Common {};

class X : public D, public B {};
class Y : public D, public C {};
Casey
  • 41,449
  • 7
  • 95
  • 125