C++ 从类(C+;+;)存储和执行函数

C++ 从类(C+;+;)存储和执行函数,c++,class,function,task,C++,Class,Function,Task,我有一个名为“Tasks”的类,它需要存储来自其他类的方法,并能够执行它们。我希望它能像这样工作: Window *window = new Window(); Tasks* tasks = new Tasks(); tasks.m_tasks.Add(window.Create("My Window")); 然后,通过迭代存储的任务并执行每个任务,我可以从tasks类调用该窗口创建: tasks.ExecuteTasks(); 存储函数的“m_tasks”的数据结构是什么?我如何调用它们?

我有一个名为“Tasks”的类,它需要存储来自其他类的方法,并能够执行它们。我希望它能像这样工作:

Window *window = new Window();
Tasks* tasks = new Tasks();
tasks.m_tasks.Add(window.Create("My Window"));
然后,通过迭代存储的任务并执行每个任务,我可以从tasks类调用该窗口创建:

tasks.ExecuteTasks();

存储函数的“m_tasks”的数据结构是什么?我如何调用它们?

为此,您需要稍微复杂的结构:

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;
类任务
{
公众:
虚空执行()=0;
};
模板
类函数1:公共任务
{
公众:
函数1(T*ptr,R(T::*fptr)(P1),P1-P1):ptr(ptr),fptr(fptr),P1(P1){}
void Execute(){(ptr->*fptr)(p1);}
私人:
T*ptr;
R(T::*fptr)(P1);
P1;
};
std::vec;

如果您知道参数是什么,那么这是相对简单的。你可以使用一个函数指针,再加上一些额外的东西,使它成为一个“方法”指针。见:


但是,这不允许您传递任意参数。你可以用C++模板来做,但是这会很糟糕。我强烈建议避免这种情况,如果可能的话,用传统的函数/方法指针。

MyTask将是某种类型的集合,除非您需要在中间添加/删除,否则我可能会使用列表。您将存储在列表中的内容是函数指针。也就是说,指向函数的指针。对于我下面的代码的简单版本,您不能有通用函数指针,必须明确参数类型和返回值类型。可以使用模板来打破这一限制。我一点也不知道

// 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;
//将FunctionPtr定义为指向函数的指针,该函数接受单个char*param并返回void
typedef void(*FunctionPtr)(字符*);
//定义stl:FunctionPtr项列表
std:列出m_任务;

如果
std::function
不可用,我会使用
std::list
,或者
boost::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"); } );
    // ...
}
类任务{
公众:
void Add(const std::function&f)
{callbacks_u.push_uback(f);}
void Add(std::function&&f)
{callbacks_u.emplace_uback(std::move(f));}
// ...
私人:
std::列表回调;
};
int main(){
窗口窗口;
// ...
tasks.Add([&](){window.Create(“我的窗口”);});
// ...
}
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" ) );
    // ...
}
类任务{
公众:
void Add(const boost::function&f)
{callbacks_u.push_uback(f);}
私人:
std::列表回调;
};
int main(){
// ...
添加(boost::bind(&Window::Create,boost::ref(Window),“我的Window”);
// ...
}

您可以像@aschepler所说的那样使用tr1或boost::函数的列表,但是这个场景非常适合您

类任务{
boost::信号m_任务;
};
// ...
tasks.m_tasks.connect(&someFunction);
//执行任务:
tasks.m_tasks();

这允许许多额外的功能,如处理参数、返回,并允许客户端在需要时断开其任务。

或者您可以将boost::function/std::function与boost::bind/lambdas结合使用,这一切都可以为您完成。这仍然很简单,每个人都需要知道它是如何完成的。无需将其隐藏在boost api:)@tp1:后面,直到您想要组合一些自由函数、一些类成员函数、一些带有绑定参数的函数。。。都在同一个容器中。@aschepler:即使在修改之后,代码也不是很复杂。事实上,lib依赖项比导致创建Function1、Function2等类的两行复制粘贴代码的问题更大。@tp1,lib依赖项是一个微不足道的问题,因为它是一个只包含头的库(对于
boost::function
),并且
std::function
在最新版本的VS和G++中内置。复制粘贴代码对于可维护性来说是个坏主意:)
class Tasks {
    boost::signal<void ()> m_tasks;
};

// ...
tasks.m_tasks.connect(&someFunction);

// ExecuteTasks:
tasks.m_tasks();