我正在设计一个设计非常糟糕的项目,我偶然发现了这个数据结构:
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") */
}
但是,由于我只是在读取数据并排队新输入,所以我想使用迭代器:
// 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?欢迎使用我设计的任何其他建议。
答案 0 :(得分: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 */
}
答案 1 :(得分:0)
你不能(据我所知)在std::vector
课程中添加新成员。但是,您可以将其子类化,因此您可以定义自己的迭代器。
另一方面,您可以为CustomBagOfData
课程添加一些新方法,例如:
public:
std::vector<Derived1*>::iterator getDerived1Begin() {
return getDerived1Datas().begin()
}
// And the same for getDerived1End
然而,尽管不知道如何实现DefinedN
类,我建议摆脱那些神奇的数字(Derived1,Derived2,......)并用参数做更优雅的事情。
答案 2 :(得分: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;
}
}