Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Separation of interface from implementation in an inheritance hierarchy (C++ newbie)

Tags:

c++

c++11

I am trying to figure out how to arrange some classes. This is what I've got so far ...

The top of the inheritance hierarchy is (naturally) T:

(T.h)
namespace foo
{
    class T
    {
    public:
        virtual void method1(std::string a_parameter) = 0;
        virtual void method2() = 0;
    };
}

I have two sub-classes of T with some additional methods - here are the header files:

(A.h)
namespace foo
{
    class A : public T
    {
    public:
        virtual ~A() {};
        virtual void method3() = 0;
        //and a factory function
        static A* gimmeAnAyy();
    };
}

(B.h)
namespace foo
{
    class B : public T
    {
    public:
        virtual ~B() {};
        virtual void method4() = 0;
        //and a factory function
        static B* gimmeABee();
    };
}

The implementation classes are in the respective .cpp files:

(A.cpp)
namespace foo
{
    class AImpl : public A
    {
    public:
        A(std::string member_data) : m_member_data(member_data) {};
        ~A() {};
        void method3()
        {
            //something really important, can't think of it right now ;-)
        };
    private:
        std::string m_member_data;
    };
    A* A::gimmeAnAyy()
    {
        return new AImpl("this is an impl of A");
    }; 
}

(B.cpp)
namespace foo
{
    class BImpl : public B
    {
    public:
        B(std::string other_data) : m_other_data(other_data) {};
        ~B() {};
        void method4()
        {
            //something really important, can't think of it right now ;-)
        };
    private:
        std::string m_other_data;
    };
    B* B::gimmeABee()
    {
        return new BImpl("this is an imll of B");
    }; 
}

Now the compiler complains - rightly so - about the virtual functions method1() and method2() that I haven't implemented in AImpl and BImpl.

What I want is a TImpl class that both AImpl and BImpl can inherit from so that I don't have to implement method1() and method2() in two different .cpp files.

Is it possible? Am I out to lunch? Am I asking too many rhetorical questions for a StackExchange post?

Thanks in advance,

Mike

like image 294
mwnorman Avatar asked Dec 19 '25 21:12

mwnorman


1 Answers

Yeah, it is possible. Common practice is to use the following snippet:

template<typename Interface>
class TImpl : public Interface
{
public:
    virtual void method1(std::string a_parameter) { /* implementation */ }
    virtual void method2() { /* implementation */ }
};

And then inherit from it as follows:

class Aimpl : public TImpl<A>
{
public:
    virtual void method3() { /* implementation */ }
};

class Bimpl : public Timpl<B>
{
public:
    virtual void method4() { /* implementation */ }
};

You can put implementation of Timpl in cpp file, but then you have to explicitly instantiate it for every possible interface. This is done as follows in the cpp:

template<typename Interface>
void Timpl<Interface>::method1(std::string a_parameter)
{
    /* implementation */
}

template<typename Interface>
void Timpl<Interface>::method2()
{
    /* implementation */
}

template class Timpl<A>;
template class Timpl<B>;
like image 125
DikobrAz Avatar answered Dec 21 '25 10:12

DikobrAz