我注意到我经常需要容器类。例如,在处理粒子系统时,我创建了一个容器类Particles
,其成员为vector<Particle*>
。然后我拨打:Particles* my_particles
,如my_particles->draw()
,在Particles.draw()
I迭代器上vector<Particle*>
,再次呼叫draw()
每个粒子。同样适用于update()
,addforce()
等成员函数。现在,我正在处理一个项目,需要一个Cube
的集合,我需要在其上调用tween()
},moveTowards()
等。
我知道我可以使用模板,但是在模板类的情况下,成员函数需要先知道。因为我想检查是否可以创建泛型类,我可以使用例如我的Cubes和Particles集合。
之前已经做过这件事的人还是可以给我一些建议呢?
亲切的问候, 波吕克斯
答案 0 :(得分:4)
简短的回答是你不能用c ++做到这一点。但是,可以使用STL算法和容器来包装此行为。
首先,您将Cube或Particle实例放入std::vector
或其他容器(就像您现在所拥有的那样)。
然后你将STL的std::for_each与std::mem_fun结合使用。
这会产生这样的结果:
std::vector<Particle*> V;
V.push_back(new Particle);
V.push_back(new Particle);
V.push_back(new Particle);
V.push_back(new Particle);
std::for_each(V.begin(), V.end(), std::mem_fun(&Particle::draw));
答案 1 :(得分:1)
不确定我是否理解,但for_each
STL算法有帮助吗? http://www.sgi.com/tech/stl/for_each.html
答案 2 :(得分:1)
我读到你问:“我可以制作一个可以用于立方体和粒子的通用容器,即使它们有不同的成员函数吗?”当然,这是最简单的部分。如果需要,您甚至可以将和粒子放在同一个容器中。如果您正在处理指针,只需使用void*
:
std::vector<void*> objects;
objects.push_back(new Particle(...));
objects.push_back(new Cube(...));
当然,你可以用void*
做很多事情,除非把它们抛回去:
for (i = objects.begin(), i != objects.end(), ++i) {
void* p = objects[i];
Particle* particle = dynamic_cast<Particle*>(p);
if (particle) {
// do particle stuff
continue;
}
Cube* cube = dynamic_cast<Cube*>(p);
if (cube) {
// do cube stuff
}
}
即使你只是在你的向量中存储粒子,比如说,你仍然需要向下投射它们:
for (i = objects.begin(), i != objects.end(), ++i) {
void* p = objects[i];
Particle* particle = dynamic_cast<Particle*>(p);
if (particle) {
// do particle stuff
} else {
// error!! I thought someone told me this thing only had Particles...
}
}
你可以看到,这样做比将它们存储在单独的向量中更为尴尬,在这些向量中你知道每个向量中每个对象的类型,而不必执行运行时向下转换来处理它们。这就是为什么这种容器通常被认为是不好的风格。
您在此区域中查看的其他可能性是boost::any
或boost::variant
,它们可以处理除指针之外的其他内容。
答案 3 :(得分:0)
据我所知,这里存在一个设计问题,你想使用相同的接口迭代不同的对象类别(Cube / Particle),但很明显它们不能共享相同的接口,如果你真的想要它,你必须在粒子和立方体的抽象基类上实现tween()和moveTowards(),并在Particles类中不实现任何东西。
答案 4 :(得分:0)
为了完整性,还有valarray,但使用vector / for_each是更好的解决方案。