我有一个名为“Tasks”的类,需要存储来自其他类的方法,并且能够执行它们。我希望它能像这样工作:
Window *window = new Window();
Tasks* tasks = new Tasks();
tasks.m_tasks.Add(window.Create("My Window"));
然后我可以通过遍历存储的任务并执行每个任务来从我的任务类调用该窗口创建:
tasks.ExecuteTasks();
存储函数的“m_tasks”的数据结构是什么,我怎么称呼它们?
答案 0 :(得分:4)
如果std::list<std::function<void()> >
不可用,我会使用boost::function
或std::function
。
您需要更改Add
调用的语法,以避免立即执行Create
方法。
C ++ 11:
class Tasks {
public:
void Add(const std::function<void()>& f)
{ callbacks_.push_back( f ); }
void Add(std::function<void()>&& f)
{ callbacks_.emplace_back( std::move( f ) ); }
// ...
private:
std::list<std::function<void()> > callbacks_;
};
int main() {
Window window;
// ...
tasks.Add( [&]() { window.Create("My Window"); } );
// ...
}
C ++ 03:
class Tasks {
public:
void Add(const boost::function<void()>& f)
{ callbacks_.push_back( f ); }
private:
std::list<boost::function<void()> > callbacks_;
};
int main() {
// ...
tasks.Add( boost::bind( &Window::Create, boost::ref(window), "My Window" ) );
// ...
}
答案 1 :(得分:1)
您可以使用@aschepler所说的tr1或boost ::函数列表,但这种情况非常适合boost::signals。
class Tasks {
boost::signal<void ()> m_tasks;
};
// ...
tasks.m_tasks.connect(&someFunction);
// ExecuteTasks:
tasks.m_tasks();
这允许许多额外的功能,例如处理参数,返回,并让客户端断开他们的任务。
答案 2 :(得分:0)
你需要稍微复杂的结构:
class Task
{
public:
virtual void Execute()=0;
};
template<class T, class R, class P1>
class Function1 : public Task
{
public:
Function1(T *ptr, R (T::*fptr)(P1), P1 p1) : ptr(ptr), fptr(fptr),p1(p1) { }
void Execute() { (ptr->*fptr)(p1); }
private:
T *ptr;
R (T::*fptr)(P1);
P1 p1;
};
std::vector<Task*> vec;
答案 3 :(得分:0)
如果您知道参数是什么,这是相对简单的。你可以使用一个函数指针,一些额外的东西使它成为一个'方法'指针。参见:
但是,这不允许您传递任意参数。您可以使用C ++模板来完成它,但这将是令人讨厌的hackery。我强烈建议避免这种情况,并尽可能使用传统的函数/方法指针。
答案 4 :(得分:0)
m_tasks将是某种类型的集合,我可能会使用列表,除非您需要能够在中间添加/删除。您将在列表中存储的内容是函数指针。也就是说,指向函数的指针。使用下面的代码的简单版本,您不能拥有泛型函数指针,您必须具体了解参数类型和返回值类型。也许可以使用模板来打破这种限制。我不知道我的头脑。
// define FunctionPtr as a pointer to a function that takes a single char* param and returns void
typedef void(*FunctionPtr)(char*);
// define an stl:list of FunctionPtr items
std:list<FunctionPtr> m_tasks;