开发者

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

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 th开发者_开发问答at seems like a lot of extra overhead.

Thanks.


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;
}


Try this:

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


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.


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.


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)


Not really a solution as it introduces the drawback of using a template for the derived class. But if that is not an issue the following could help

struct MyInterface
{
    virtual void foo () const = 0;
};

struct MySpecialInterface : public MyInterface
{
    virtual void bar () const = 0;
};

template <typename Base>
struct MyDerived : public Base
{
    // only if you want to make sure that MyDerived implements
    // MyInterface
    static_assert (std::is_base_of_v<MyInterface, Base>);

    void foo () const final {}
};

struct MyImpl : public MyDerived<MySpecialInterface> {
    void bar () const final {}
};

// MyImpl now implements foo and bar. This code compiles and links at least in VS 2022
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜