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

しかし、それはひどいです。

4

3 に答える 3

1

push_backfromBaseQueueは継承チェーンの側で実装されていないBaseDequeため、最下位のクラスは依然として抽象的です。

ここで存在してはならない階級関係を強制しようとしていると思います。標準ライブラリdequeで とvectorが異なるコンテナ タイプであり、queueこれらのコンテナを継承しようとするのではなく、非常に正確なインターフェイスに適合させる方法に注意してください。

于 2011-03-14T21:11:22.120 に答える
0

ダイヤモンドの問題を解決したとしても (または @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?
    }
};
于 2011-03-14T22:04:42.417 に答える
0

たとえば、多重継承と静的ポリモーフィズムが役立ちます。

// 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; 
} 
于 2011-03-14T23:04:52.717 に答える