2010-02-03 71 views
3

我有一個自定義容器,它以兩種不同的方式實現,但只有一個接口。有些事情是這樣的。具有派生類的自定義容器的迭代器

class Vector 
    { 
     virtual Iterator begin() = 0; 
     virtual Iterator end() = 0 ; 

    ... // some more functions. 
    } ; 

    class VectorImplA : public Vector 
    { 
     Iterator begin() { return m_data.begin() ; } 
     Iterator end() { return m_data.end() ; } 
    private: 
     SomeFloatContainer m_data ; 
    } ; 

    class VectorImplB : public Vector 
    { 
     Iterator begin() { return m_data.end() ; } 
     Iterator end() ; { return m_data.end() ; } 


    private: 
     std::vector <float> m_data ; 

    } ; 

我需要的是一個Iterator的統一接口,以便我可以在基類中使用它。有任何想法嗎 ?

回答

7

我以前遇到過這個問題。雖然有辦法解決你的問題,但你很可能應該放棄一個向量基類的想法。你可能應該做的是模仿C++ STL容器的設計方式。

STL由概念而不是基類組成。 std::vectorContainer概念的模型,但不是從Container基類繼承而來的。一個概念是任何概念模型都應遵守的一系列要求。例如,請參閱this頁面,瞭解Container的要求。

Container狀態。例如,你應該的typedef容器的內容的類型爲value_type,和迭代器的typedef作爲iteratorconst_iterator的要求。此外,您應該定義返回迭代器的函數begin()end(),依此類推。

然後,您需要更改在您的基類上運行的函數,而不是在符合該概念強加的要求的任何類上運行。這可以通過使功能模板化來完成。你不一定要堅持STL使用的概念,你可以自己做。堅持STL中定義的概念,STL算法(例如,std::sort)可以在您的容器上運行。

簡單的例子:

class VectorImplA 
{ 
public: 
    typedef VectorImplAIterator iterator; 

    iterator begin(); 
    iterator end(); 
}; 

class VectorImplB 
{ 
public: 
    typedef VectorImplBIterator iterator; 

    iterator begin(); 
    iterator end(); 
}; 

template <typename VectorConcept> 
void doSomeOperations(VectorConcept &container) 
{ 
    VectorConcept::iterator it; 
    it = container.begin(); 
} 

int main() 
{ 
    VectorImplA vecA; 
    VectorImplB vecB; 
    doSomeOperations(vecA); // Compiles! 
    doSomeOperations(vecB); // Compiles as well! 
} 

作爲獎勵,回答原來的問題,考慮下面的設計(我不會去,雖然這種方式!):

struct IteratorBase 
{ 
    virtual void next() = 0; 
}; 

struct IteratorA : IteratorBase 
{ 
    void next() {}; 
}; 

struct IteratorB : IteratorBase 
{ 
    void next() {}; 
}; 

class Iterator 
{ 
    IteratorBase *d_base; 
public: 
    void next() { d_base->next(); } 
}; 
+0

+1雖然我絕對不會使用'next'操作,更好地堅持與STL互操作的慣例。 – 2010-02-03 14:37:22

+0

感謝您的答案。我已經實現了上面概述的#1。與此問題是我不能有運行時多態性。即從基類Vector中導出VectorImplA和VectorImplB,並使用Vector *來操作派生類。我對麼 ? – Surya 2010-02-03 15:17:15

0

一種可能性是爲您的容器使用模板類,並將私有數據容器作爲參數。這樣,迭代器可以在獨立於數據容器的類中定義。
我只是不確定這是否足夠「統一」你所需要的。

0

我所面臨的同樣的問題之前。我用的解決方案#2稍加修改定義迭代器類

class Iterator :public boost::iterator_facade<Iterator,element_type, forward_traversal_tag> 
{ 
    ... 
} 

這樣我就能夠使用STL算法與我的容器。