views:

159

answers:

6

In C++ is it possible to use another base class to provide the implementation of an interface (i.e. abstract base class) in a derived class?

class Base
{
    virtual void myfunction() {/*...*/};
}
class Interface
{
    virtual void myfunction() = 0;
}
class Derived
    : public Base, public Interface
{
    // myfunction is implemented by base
}

The above should compile, but doesn't actually work. Is there any way to achieve this effect?

In case anyone cares, the reason for wanting this is that it make sense (for my application) to use a generic library from another project/namespace to provide the implementation of an interface in my project. I could just wrap everything, but that seems like a lot of extra overhead.

Thanks.

+1  A: 

Does this work if you inherit from Interface using virtual inheritance not public?

Steve Townsend
I doubt it, this is not relevant. Sorry.
Steve Townsend
I wondered about this too, but didn't try it because it seemed to be an incorrect use of virtual inheritance according to the documentation. I just tried it though and it in fact does not work.
deuberger
+7  A: 

Try this:

class Interface
{
    virtual void myfunction() = 0;
}
class Base : public Interface
{
    virtual void myfunction() {/*...*/};
}
class Derived
    : public Base
{
    // myfunction is implemented by base
}
amuliar
Of course, this is the prefered way. However, OP says he wants "to use a generic library from another project/namespace to provide the implementation of an interface in my project." Thus I don't think he can derive Base from Interface.
Sjoerd
I could do that since I control both libraries and I thought about it, but it doesn't really make sense to me from a design stance. The other library has no reason to implement this interface and I think it would confuse other users of the library.
deuberger
+1  A: 

The response is assuming that the derived class wants to be a CONCRETE class or a non abstract class, i.e it is desired to be able to instantiate objects of type 'Derived'.. Also I assume public member functions in my response.

No. The derived class has to implement all the pure virtual functions which it inherits from all the base classes. In this case 'Base::myfunction' though inherited by 'Derived' is not treated as an implementation of 'Derived::myfunction'

'Derived::myfunction' still has to provide an implementation of 'Interface::myfunction'.

One possibility may be that 'Derived::myfunction' can internally delegate to 'Base::myfunction'

However if it not desired for Derived to be a concrete class (which I doubt is the intent of OP), then the above arrangement of classes is fine (from language perspective)

Chubsdad
+1  A: 

Base and Interface are totally different types. How is the compiler supposed to know that "myfunction" is related? You must implement it in Derived, even if that implementation merely calls the Base version.

DeadMG
+2  A: 

No. (not that way anyway)

You might be mislead by the way things are done in other languages like Java, C#, ActionScript, etc.

In C++, multiple inheritance and the way virtual classes are managed makes interfaces (as used in other languages) obsolete. In those other languages, interfaces are used to fix problems issued from the lack of multiple inheritance (good or bad, it's a choice).

So if what you want to do is just provide a general interface with some virtual methods providing default implementations, just implement in the base class :

class Interface
{
    virtual void myfunction() { /*...*/ } ; //default implementation
    virtual void yourFunction()  = 0 ; // this one HAVE TO be implemented by the user
}
class Derived
    : public public Interface // dont' need another clas
{
    // myfunction is implemented by base
    void yourFunction(); // have to implement yourFunction
}
class DerivedB
    : public public Interface // dont' need another clas
{
    void myFunction();// myfunction is implemented by base but we implement it for this specific class
    void yourFunction(); // have to implement yourFunction
}

If however, you want to provide several base classes that have the same interfaces, then think that your interface class is the bases of the other classes

// in this order
class Interface
{
    virtual void myfunction() = 0;
}
class BaseA : public Interface
{   
    // here "virtual" is optional as if the parent is virtual, the child is virtual too
    virtual void myfunction() {/*...*/}; // BaseA specific implementation
}
class BaseB : public Interface
{
    virtual void myfunction() {/*...*/}; // BaseB specific implementation
}

There is however a not-really-easy-to-read (read: not recommanded) way to provide a default implementation BUT forcing the user to explicitely say if he want to use it or not. It exploit the fact that even pure virtual functions can have default implementations that can be called :

class Interface
{
    virtual void myfunction() { /*...*/ } ; //default implementation
    virtual void yourFunction()  = 0 ; // this one HAVE TO be implemented by the user BUT provide a default implementation!
}

// in Interface.cpp 

void Interface::yourFunction() // default implementation of the virtual pure function
{ /*...*/ }

// in Derived.h

class DerivedA
    : public public Interface // dont' need another clas
{
    // myfunction is implemented by base
    void yourFunction(); // have to implement yourFunction -- DerivedA specific
}

class DerivedB
    : public public Interface // dont' need another clas
{
    void myFunction();// myfunction is implemented by base but we implement it for this specific class
    void yourFunction() { Interface::yourFunction(); } // uses default implementation of yourFunction, hidden but existing
}

But don't do it.

Klaim
+1 for mentioning that C++ and Java/C# differ on this point.
Sjoerd
You're right, I originally had the idea based on my experience in Java and C#, but then realized the same thing wouldn't work in C++. I'm not sure whether I think that's good or bad yet, it would certainly be easier if it worked, but I know there's a good reason that it doesn't.
deuberger
You have more choice than in those previous languages, but that gives you more consequences too. I would be you, the only question would be : will I provide multiple default implementations? If no, go with the first simple solution (Just define default implementation in non-pure virtual functions); otherwise, you need a "concept hierarchy", represented by your class hierarchy as the second example.
Klaim
+2  A: 

If Base doesn't derived from Interface, then you'll have to have forwarding calls in Derived. It's only "overhead" in the sense that you have to write extra code. I suspect the optimizer will make it as efficient as if your original idea had worked.

class Interface {
    public:
        virtual void myfunction() = 0;
};

class Base {
    public:
        virtual void myfunction() {/*...*/}
};

class Derived : public Interface, public Base {
    public:
        void myfunction() { Base::myfunction(); }  // forwarding call
};

int main() {
   Derived d;
   d.myfunction();
   return 0;
}
Adrian McCarthy
This is what I was guessing I'd have to end up doing. Do I have to explicitly forward it or is there a way to achieve the same thing with a using directive? (e.g. using Base::myfunction();). Would that work?
deuberger
Does anyone know for sure whether the optimizer would actually make this equally as efficient? I'm using gcc 4.5.1 on fedora 13.
deuberger