2013-04-04 85 views
0

我工作的一個實在太差了設計項目,我已經在這個數據結構跌跌撞撞:如何創建特定的std :: vector迭代器?

class OldBagOfData 
{ 
public: 
    std::vector< BaseClass* > baseDatas; 
    std::vector< Derived1* > derived1Datas; 
    std::vector< Derived2* > derived2Datas; 
    std::vector< Derived3* > derived3Datas; 
    std::vector< Derived4* > derived4Datas; 

} 

更新的類的方法是使用一個可怕的很多的if/else條件語句(幾十)並且成員是可修改的(最重要的是它使用指針而不是實例),儘管我們只是讀取數據。

class CurrentBagOfData 
{ 
private: 
    std::vector< BaseClass* > genericContainer; 

    Template< typename DataType> 
    std::vector< DataType* > getData(datatype IDtype); 

public: 
    std::vector< BaseClass* > getbaseDatas(); /* = getData<Base>("base") */ 
    std::vector< Derived1* > getDerived1Datas(); /* = getData<Derived1>("derived1") */ 
    std::vector< Derived2* > getDerived2Datas(); /* = getData<Derived2>("derived2") */ 
    std::vector< Derived3* > getDerived3Datas(); /* = getData<Derived3>("derived3") */ 
    std::vector< Derived4* > getDerived4Datas(); /* = getData<Derived4>("derived4") */ 

} 

然而,因爲我只是讀DATAS和排隊新的輸入,我想用迭代器:

// This loop is forbidden because obod.getDerived1Datas() is a temporary object 
for(std::vector<Derived1*>::iterator it = obod.getDerived1Datas().begin(); 
             it != obod.getDerived1Datas().end(); i++) 
{ 
    /* processing *it */ 
} 

//What I want to do : 
for(std::vector<Derived1*>::iteratorDerived1 it = obod.begin(); it != obod.end(); i++) 
{ 
    // it iterate over every Derived1 datas in the generic container 
    /* processing *it */ 
} 

我已經通過使用通用的功能和模板簡化了代碼

如何創建std :: vector :: iteratorDerivedX?歡迎對我設計的任何其他建議。

+1

爲什麼你不返回對get *函數中的向量的引用?嘗試返回迭代器時會出現什麼樣的錯誤? – 2013-04-04 11:26:13

+0

所以在你的「當前」中你有一個主向量,並且當你需要模板函數中的派生版本(是嗎?)時複製它,並返回臨時值。我可能會問的一件事是矢量(儘管重複)的損失是否會導致速度放慢 - 是否首先出現速度重複? – Caribou 2013-04-04 11:33:58

+0

@ W.B:當直接使用迭代器時,我得到運行時錯誤「vector not derefenced」(或多或少)。 – lucasg 2013-04-04 11:48:53

回答

0

我找到了一個使用模板迭代器的方法。不幸的是它增加了很多開銷,所以我不確定我會用它:

#include <iostream> 
#include <vector> 

typedef std::string datatype ; 

class BaseClass{ 
public: 
    BaseClass():type("base"){} 
    datatype type; 

}; 

class Derived1 : public BaseClass{ 
public: 
    Derived1(){ type= "derived1"; } 
}; 
class Derived2 : public BaseClass{ 
public: 
    Derived2(){ type ="derived2"; } 
}; 
class Derived3 : public BaseClass{ 
public: 
    Derived3(){ type ="derived3"; } 
}; 
class Derived4 : public BaseClass{ 
public: 
    Derived4(){ type ="derived4"; } 
}; 


class CurrentBagOfData 
{ 
private: 


    template< typename DataType> 
    std::vector< DataType* > getData(datatype IDtype) 
    { 
     std::vector< DataType* > output; 
     for(int i=0; i< genericContainer.size(); i++) 
     { 
      if(genericContainer[i]->type == IDtype) 
      { 
       output.push_back((DataType*) genericContainer[i]); 
      } 

     } 
     return output; 
    } 

public: 

    // Begin of the specialized container 
    template< class DataType> 
    std::vector< BaseClass* >::iterator begin() 
    { 
     std::vector< BaseClass* >::iterator it = genericContainer.begin(); 


     datatype type = DataType().type; 
     while(it != genericContainer.end() && (*it)->type != type ) 
     { 
      it++; 
     } 

     return it; 

    } 

    // End of the specialized container 
    template< class DataType> 
    std::vector< BaseClass* >::iterator end() 
    { 
     std::vector< BaseClass* >::iterator it = genericContainer.begin(); 
     std::vector< BaseClass* >::iterator output = it; 

     datatype type = DataType().type; 
     while(it!= genericContainer.end()) 
     { 
      it++; 


      if(it!= genericContainer.end() && (*it)->type == type) 
      { 

       output = it; 
      } 

     } 



     return output; 

    } 


    // Iterate over a certain type of elements in the container 
    template< class DataType> 
    void gen(std::vector<BaseClass*>::iterator &it) 
    { 
     const std::vector< BaseClass* >::iterator e = this->genericContainer.end(); 

     // Mandatory increment 
     if(it!= e) 
      it++; 

     // Loop until next DataType elem 
     datatype type = DataType().type; 
     while(it!= e && (*it)->type != type ) 
     { 
      it++; 
     } 

    } 


    std::vector< BaseClass* > getbaseDatas(){ return getData<BaseClass>("base"); } 
    std::vector< Derived1* > getDerived1Datas(){ return getData<Derived1>("derived1"); } 
    std::vector< Derived2* > getDerived2Datas(){ return getData<Derived2>("derived2"); } 
    std::vector< Derived3* > getDerived3Datas(){ return getData<Derived3>("derived3"); } 
    std::vector< Derived4* > getDerived4Datas(){ return getData<Derived4>("derived4"); } 


    std::vector< BaseClass* > genericContainer; 






}; 



int main() 
{ 
    // Object 
    CurrentBagOfData cbod; 

    cbod.genericContainer.push_back(new(BaseClass)); 
    cbod.genericContainer.push_back(new(Derived1)); 
    cbod.genericContainer.push_back(new(Derived3)); 
    cbod.genericContainer.push_back(new(Derived2)); 
    cbod.genericContainer.push_back(new(Derived1)); 
    cbod.genericContainer.push_back(new(Derived4)); 
    cbod.genericContainer.push_back(new(Derived3)); 
    cbod.genericContainer.push_back(new(Derived3)); 

    // Loop on Derived4 object, using the original method 
    std::vector< Derived4* > o = cbod.getDerived4Datas(); 
    for (int i=0; i < o.size(); i++) 
    { 
     std::cout << o[i]->type << std::endl; 
    } 
    std::cout << std::endl; 

    // Loop on Derived3 objects, with custom iterators. 
    std::vector< BaseClass* >::iterator it; 
    for(it = cbod.begin<Derived3>(); it <= cbod.end<Derived3>(); cbod.gen<Derived3>(it)) 
    { 
     std::cout << (*it)->type << std::endl; 
    } 

} 
+0

阿科波爾德的答案是正確的。 – jthill 2013-05-14 17:13:20

+0

雖然在技術上是正確的,但我很困擾這樣一個事實,即必須先創建一個矢量的本地副本,然後才能對其進行迭代。用這種方法,沒有副本,只有引用。 – lucasg 2013-05-14 20:32:41

+0

當一個對象從一個函數的返回值被初始化時,編譯器通常只是在那裏構造它。它被稱爲「返回值優化」。這些日子的編譯人員非常非常善於提煉這樣的抽象懲罰。 – jthill 2013-05-14 20:49:22

1

你可以在for循環之前保存函數調用的返回值;

另外,您每次迭代都調用end()方法,這可能很昂貴。

對於迭代器,pos增量比預增量器要貴。

std::vector<Derived1*> tmp = obod.getDerived1Datas(); 
for(std::vector<Derived1*>::iterator it = tmp.begin(), ed = tmp.end(); it != ed; ++i) 
{ 
    /* processing *it */ 
} 
0

您可以將新成員,他不(據我所知)添加到std::vector類。但是,您可以對其進行子類化,因此您可以定義自己的迭代器。

在另一方面,你可以添加一些新的方法,以你的CustomBagOfData類,類似:

public: 
    std::vector<Derived1*>::iterator getDerived1Begin() { 
     return getDerived1Datas().begin() 
    } 
    // And the same for getDerived1End 

然而,儘管不知道DefinedN類是如何實現的,我建議你擺脫那些神奇的數字(Derived1,Derived2,...),並用參數做更優雅的事情。

+0

我曾想過讓NewBagOfDatas從std :: vector 繼承,但該類已經是來自接口的子類,我寧願不做多重繼承。而getDerivedN只是臨時柺杖以應付複雜的應用程序。 – lucasg 2013-04-04 11:32:19

相關問題