Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: Derived + Base class implement a single interface?

In C++, is it possible to have a base plus derived class implement a single interface?

For example:

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

class Base
{
    public:
        virtual void BaseFunction(){}
};

class Derived : public Base, public Interface
{
    public: 
        void DerivedFunction(){}
};

void main()
{
    Derived derived;
}

This fails because Derived can not be instantiated. As far as the compiler is concerned Interface::BaseFunction is never defined.

So far the only solution I've found would be to declare a pass through function in Derived

class Derived : public Base, public Interface
{
    public: 
        void DerivedFunction(){}
        void BaseFunction(){ Base::BaseFunction(); }
};

Is there any better solution?


EDIT: If it matters, here is a real world problem I had using MFC dialogs.

I have a dialog class (MyDialog lets say) that derives from CDialog. Due to dependency issues, I need to create an abstract interface (MyDialogInterface). The class that uses MyDialogInterface needs to use the methods specific to MyDialog, but also needs to call CDialog::SetParent. I just solved it by creating MyDialog::SetParent and having it pass through to CDialog::SetParent, but was wondering if there was a better way.

like image 505
Joe Avatar asked Nov 14 '08 18:11

Joe


3 Answers

C++ doesn't notice the function inherited from Base already implements BaseFunction: The function has to be implemented explicitly in a class derived from Interface. Change it this way:

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

class Base : public Interface
{
    public:
        virtual void BaseFunction(){}
};

class Derived : public Base
{
    public: 
        virtual void DerivedFunction(){}
};

int main()
{
    Derived derived;
}

If you want to be able to get away with only implementing one of them, split Interface up into two interfaces:

class DerivedInterface
{
    public:
        virtual void DerivedFunction() = 0;
};

class BaseInterface
{
    public:
        virtual void BaseFunction() = 0;
};

class Base : public BaseInterface
{
    public:
        virtual void BaseFunction(){}
};

class Derived : public DerivedInterface
{
    public: 
        virtual void DerivedFunction(){}
};  

class Both : public DerivedInterface, public Base {
    public: 
        virtual void DerivedFunction(){}
};

int main()
{
    Derived derived;
    Base base;
    Both both;
}

Note: main must return int
Note: it's good practise to keep virtual in front of member functions in the derived that were virtual in the base, even if it's not strictly required.

like image 113
Johannes Schaub - litb Avatar answered Nov 20 '22 20:11

Johannes Schaub - litb


It looks like it's not quite the case that Derived "is-a" Base, which suggests that containment may be a better implementation than inheritance.

Also, your Derived member functions should be decalred as virtual as well.

class Contained
{
    public:
        void containedFunction() {}
};

class Derived
{
    public:
        virtual void derivedFunction() {}
        virtual void containedFunction() {return contained.containedFunction();}
    private:
        Containted contained;
};

You can make the contained member a reference or smart pointer if you want to hide the implementation details.

like image 38
JohnMcG Avatar answered Nov 20 '22 20:11

JohnMcG


The problem is that with your example, you have two implementations of Interface, the one coming from Base and the one coming from Derived. This is by design in the C++ language. As already pointed out, just remove the Interface base class on the definition of Derived.

like image 1
Torlack Avatar answered Nov 20 '22 18:11

Torlack