2013-04-04 78 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

相关问题