2014-04-03 64 views
1

我有以下類別: //在concreteIterator.h關於模板的傳承

template<class Item> 
    class concreteForwardItr : public iterator<Item> 
{ 

public: 
    concreteForwardItr(){} 
    concreteForwardItr(List<Item> *theList){ 
     // this->iterator(); 
     targetList = theList; 
     currentPos = 0; 
    } 

    void first(){ 
     currentPos = 0; 
    } 

    Item CurrentItem() const { 
    // return targetList-> 
    if(!IsDone()) 
    { 
     return targetList->get(currentPos); 
    } 

    private: 
    List<Item>* targetList; 

    //keep track of current position 
    long currentPos; 
} 

//iterator.h 
template <class Item> 
class iterator{ 
public: 
    virtual void first() =0; 
    virtual Item CurrentItem() = 0; 
} 

但編譯器抱怨:未定義的引用「迭代器:迭代()」

但我不甚至可以調用該函數。我知道編譯器會爲列表類生成一個默認值。有沒有人看到問題是什麼?

+0

'iterator'的默認構造函數由'concreteForwardItr'的構造函數隱式調用。想知道,是否在程序外部的庫中定義了'iterator'?這似乎錯誤是由鏈接器提出的。 –

+0

@faranwath不,迭代器只是我在同一個項目中編寫的另一個文件。從有效的C++中,我知道如果從模板基類繼承,大多數編譯器不會查看基類。我嘗試使用書中建議的方法,但仍然沒有發生運氣。 – user2984297

+0

您是否嘗試明確調用'iterator'的構造函數? –

回答

2

首先,讓我們把這個正確的順序:

template <class Item> 
class iterator{ 
public: 
    virtual void first() = 0; 
    virtual Item CurrentItem() = 0; 
} 


template<class Item> 
    class concreteForwardItr : public iterator<Item> 
{ 

public: 
    concreteForwardItr(){} 
    concreteForwardItr(List<Item> *theList){ 
     // this->iterator(); 
     targetList = theList; 
     currentPos = 0; 
    } 

    void first(){ 
     currentPos = 0; 
    } 

    Item CurrentItem() const { 
    // return targetList-> 
    if(!IsDone()) // what is `IsDone`? 
    { 
     return targetList->get(currentPos); 
    } 
    // where's the closing brace? 

    private: 
    List<Item>* targetList; 

    //keep track of current position 
    long currentPos; 
} 

一個問題,這是concreteForwardItr::CurrentItem不會覆蓋iterator::CurrentItem,因爲前者是const而不是後者。你應該總是使用「關鍵詞」 override當你要覆蓋一個虛函數(如果你的編譯器支持的話):

Item CurrentItem() const override 
{ /* ... */ } 

這將產生一個編譯器錯誤沿錯誤的線路:功能不會覆蓋任何基類虛函數

要使concreteForwardItr::CurrentItem覆蓋iterator::CurrentItem請調整其中一個的常數限定。你應該調整哪一個是設計決定;如果接口聲明成員函數爲const,那麼實現不能改變它。

我已經評論了第一個代碼塊中的另外兩個可能的問題。請注意,在源文件(.cpp)中,類模板iterator應發生在concreteForwardItr(「正確的順序」)之前。


您可能要考慮重新命名這個類,因爲它滿足了一個範圍而不是一個C++ 迭代的C++的概念。

虛擬函數通常具有運行時開銷,迭代器/範圍通常用於循環中。這可能是標準庫(和boost範圍IIRC)爲其自己的迭代器/範圍類不使用類層次結構設計的原因之一,而是與實現一些抽象概念並與通用算法結合的不相關類。算法也與迭代器的類設計分離,它們只需要這個概念。

+0

好評論那裏。我抄錄了部分代碼,使其更加清晰,但不幸的是,這使得更加混亂。所以對於你答案的最後部分,正是我想學習的迭代器模式。但我應該使用具體的類來擺脫虛函數的開銷,以使其更加高效。 – user2984297