C++: using a base class as the implementation of an interface

13,780

Solution 1

If Base isn'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;
}

Solution 2

Try this:

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

Solution 3

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 Interface // don't need another class
{
    // myfunction is implemented by base
    void yourFunction(); // have to implement yourFunction
};
class DerivedB
    : public Interface // don't need another class
{
    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 Interface // don't need another class
{
    // myfunction is implemented by base
    void yourFunction(); // have to implement yourFunction -- DerivedA specific
};

class DerivedB
    : public Interface // don't need another class
{
    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.

Solution 4

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)

Solution 5

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.

Share:
13,780
deuberger
Author by

deuberger

Updated on June 07, 2022

Comments

  • deuberger
    deuberger about 2 years

    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.

  • Sjoerd
    Sjoerd almost 14 years
    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.
  • deuberger
    deuberger almost 14 years
    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
    deuberger almost 14 years
    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
    deuberger almost 14 years
    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
    deuberger almost 14 years
    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.
  • Klaim
    Klaim almost 14 years
    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.
  • LINEMAN78
    LINEMAN78 over 9 years
    While this is the most complete answer, I think this is a bug in the way C++ handles this and/or a poor design choice in the way virtual methods are linked. I will preface with the fact that I am a Java dev now working in C++, but I think this class hierarchy is valid and should work without having to forward an interface method to the parent manually. An interface IA is implemented in the abstract class AbstractA and also extended by IB. Class C extends AbstractA and implements IB, it now has to forward IA methods to the AbstractA implementations even though the method sigs are the same.
  • Brandlingo
    Brandlingo over 2 years
    Base::myfunction() need not be virtual, it is called statically anyway. Also it might be an idea to privately inherit from Base since this is an implementation detail, not an "is-a" relationship.
  • Brandlingo
    Brandlingo over 2 years
    (even better would be to favor composition over inheritance)
  • Brandlingo
    Brandlingo over 2 years
    A using declaration (using Base::myfunction;) would not work, Derived would remain abstract. This is because Derived contains Interface::myfunction() and Base::myfunction(). Base::myfunction is public and you inherit publicly, so the using declaration will not change anything.