Программирование в стиле интерфейса C ++. Нужен выход - PullRequest
1 голос
/ 14 марта 2011
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;
}

У меня такая ошибка: "C2259: 'VectorDeque': невозможно создать экземпляр абстрактного класса ...".Как я могу это исправить?Класс VectorQueue уже реализовал каждый виртуальный метод класса BaseQueue.Но компилятор этого не знает.Единственный способ, которым я вижу, - написать что-то вроде этого:

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

Но это ужасно.

Ответы [ 3 ]

1 голос
/ 15 марта 2011

push_back из BaseQueue не реализовано на стороне BaseDeque цепочки наследования, и, таким образом, самый дочерний класс все еще абстрактный.

Я думаю, что вы пытаетесь форсировать классотношения здесь, которые не должны существовать.Обратите внимание, что в стандартной библиотеке deque и vector существуют разные типы контейнеров, а такие вещи, как queue, адаптируют эти контейнеры к очень точным интерфейсам, а не пытаются наследовать.

0 голосов
/ 15 марта 2011

Множественное наследование и статический полиморфизм помогают, например:

// 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; 
} 
0 голосов
/ 15 марта 2011

Даже если вы решите проблему с бриллиантами (или последуете совету @Mark B и не будете их разлучать), у вас есть еще несколько проблем:

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