ChessMax
ChessMax

Reputation: 2265

C++ interface style programming. Need a way out

template <typename T>
class BaseQueue
{
    public :
    virtual void push_back(T value) = 0;
    //other  virtual methods
};

template <typename T>
class BaseDeque: public virtual BaseQueue<T>
{
    public:
        virtual void push_front(T value) = 0;
        //other virtual methods
};

//Realisation
template <typename T>
class VectorQueue: public BaseQueue<T>
{
    typedef typename std::vector<T> array;
    private: array adata;
    public:
    VectorQueue()
    {
       adata = array();
    }

    void push_back(T value)
    {
        adata.push_back(value);
    }
};

template <typename T>
class VectorDeque: virtual public VectorQueue<T>, virtual protected BaseDeque<T>//, 
{
    void push_front(T value)
    {
        VectorQueue::adata.push_front(value);
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    VectorDeque<int> vd = VectorDeque<int>();//here is a error

    int i;
    std::cin >> i;
    return 0;
}

I have such error: "C2259: 'VectorDeque' : cannot instantiate abstract class ...". How can I fix it? Class VectorQueue has realize every virtual method of BaseQueue class already. But the compiler doesn't know it. The only way I see is to write something like this:

template <typename T>
class VectorDeque: virtual public VectorQueue<T>, virtual protected BaseDeque<T>//, 
{
    void push_front(T value)
    {
        VectorQueue::adata.push_front(value);
    }
    void push_back(T value)
    {
        VectorQueue::push_back(value);
    }
    //repeat it fo every virtual method of BaseQueue class (interface)
};

But it's awful.

Upvotes: 1

Views: 352

Answers (3)

Alain Rist
Alain Rist

Reputation: 837

Multiple inheritance and static polymorphism are of help, for instance:

// Abstract bases
template <typename T, typename Val> 
class BaseQueue 
{     
public :     
    void push_back(Val val)
    {
        static_cast<T*>(this)->push_back(val); 
    }
    // ...
};  
template <typename T, typename Val> 
class BaseDeque
{     
public:         
    void push_front(Val val)
    {
        static_cast<T*>(this)->push_front(val); 
    }
    // ...
};

// Concrete class
#include <deque>
template <typename Val> 
class QueueDeque: 
    public BaseQueue<QueueDeque<Val>, Val>,
    public BaseDeque<QueueDeque<Val>, Val>
{   
    std::deque<Val> vals;
public:
    void push_front(Val val)
    {
        vals.push_front(val); 
    }
    void push_back(Val val)
    {
        vals.push_back(val); 
    }
    // etc..
};  
int main() 
{     
    QueueDeque<int> vd;// no more error      
    vd.push_front(5);
    vd.push_back(0);
    return 0; 
} 

Upvotes: 0

Tim
Tim

Reputation: 9172

Even if you solve your diamond issue (or follow @Mark B's advice and keep them separate), you have a few other issues in there:

template <typename T>
class VectorQueue: public BaseQueue<T>
{
    typedef typename std::vector<T> array;
    private: array adata;   // if this is private, VectorDeque can't reach it

    public:
    // constructors have an initializer section
    // member variables should be initialized there, not in the body
    VectorQueue()
    // : adata()  // however, no need to explicitly call default constructor
    {
       // adata = array();
    }
};


template <typename T>
class VectorDeque: virtual public VectorQueue<T>, virtual protected BaseDeque<T>
{
    void push_front(T value)
    {
        // if adata is protected, you can just access it.  No need for scoping
        /*VectorQueue::*/  adata.push_front(value);
        // Error:  std::vector doesn't have a method push_front.
        // Perhaps you meant to use std::list?
    }
};

Upvotes: 0

Mark B
Mark B

Reputation: 96241

push_back from BaseQueue isn't implemented on the BaseDeque side of the inheritance chain, and thus the childmost class is still abstract.

I think you're trying to force a class relationship here that shouldn't exist. Note how in the standard library deque and vector are distinct container types and things like queue adapt those containers to very precise interfaces rather than trying to inherit.

Upvotes: 1

Related Questions