假设我有一个50到200之间的大型单个函数池,它们的工作就是对单个对象进行操作并对其进行修改。函数池有选择地放入一个数组中,并按任意顺序排列。
函数本身不会在它正在修改的对象中出现的值之外使用任何参数,并且以这种方式,对象的行为仅由执行哪些函数以及以什么顺序确定。
到目前为止,我暂时使用的一种方法是,这可以更好地解释我的目标是什么:
class Behavior{
public:
virtual void act(Object * obj) = 0;
};
class SpecificBehavior : public Behavior{
// many classes like this exist
public:
void act(Object * obj){ /* do something specific with obj*/ };
};
class Object{
public:
std::list<Behavior*> behavior;
void behave(){
std::list<Behavior*>::iterator iter = behavior.front();
while(iter != behavior.end()){
iter->act(this);
++iter;
};
};
};
我的问题是,在性能和可维护性方面,C ++组织这样一个功能池的最有效方法是什么。这是针对我正在进行的一些A.I研究,这种方法与我想要达到的最接近。
编辑:阵列本身可以随时由此处未列出的代码的任何其他部分进行更改,但保证在调用behave()
期间永远不会更改。它存储的数组需要能够改变并扩展到任何大小
答案 0 :(得分:5)
如果行为函数没有状态且只接受一个Object
参数,那么我将使用一个函数对象的容器:
#include <functional>
#include <vector>
typedef std::function<void(Object &)> BehaveFun;
typedef std::vector<BehaveFun> BehaviourCollection;
class Object {
BehaviourCollection b;
void behave() {
for (auto it = b.cbegin(); it != b.cend(); ++it) *it(*this);
}
};
现在您只需要将所有功能加载到集合中。
答案 1 :(得分:2)
如果您要对此集合执行的主要操作是迭代它,您可能希望使用vector
作为解除引用,并且递增迭代器将等同于简单的指针算法。
如果您想使用所有内核,并且您的操作不共享任何状态,您可能需要查看像英特尔TBB这样的库(请参阅parallel_for example)
答案 2 :(得分:2)
我会完全按照你的要求保留它。 Perofmance应该没问题(由于vtable查找可能会有额外的间接,但这无关紧要。)
保持原样的理由是:
您可以将常见的子行为提升为行为与实现类之间的中间类。使用函数指针并不容易。
struct AlsoWaveArmsBase : public Behaviour
{
void act( Object * obj )
{
start_waving_arms(obj); // Concrete call
do_other_action(obj); // Abstract call
end_waving_arms(obj); // Concrete call
}
void start_waving_arms(Object*obj);
void end_waving_arms(Object*obj);
virtual void do_other_actions(Object * obj)=0;
};
struct WaveAndWalk : public AlsoWaveArmsBase
{
void do_other_actions(Object * obj) { walk(obj); }
};
struct WaveAndDance : pubic AlsoWaveArmsBase
{
void do_other_actions(Object * obj) { walk(obj); }
}
您可能希望在行为中使用州
struct Count : public Behavior
{
Behaviour() : i(0) {}
int i;
void act(Object * obj)
{
count(obj,i);
++i;
}
}
您可能想要添加辅助功能,例如您可能想要添加can_act
这样的内容:
void Object::behave(){
std::list<Behavior*>::iterator iter = behavior.front();
while(iter != behavior.end()){
if( iter->can_act(this) ){
iter->act(this);
}
++iter;
};
};
答案 3 :(得分:1)