【问题标题】:std::function vs Lambda for passing member functionsstd::function vs Lambda 用于传递成员函数
【发布时间】:2017-01-18 14:23:57
【问题描述】:

我正在为游戏引擎创建一个消息传递系统,其中引擎的最终用户可以创建一个消息对象并将其传递给一个游戏对象,以便由包含附加到游戏对象的组件的侦听器对象解释。如果消息与侦听器正在侦听的消息匹配,则侦听器应调用函数指针并将接收到的消息传递给它。基本结构如下所示:

class Message
{
    std::string message;
};

class Listener
{
    std::string target;
    void (*fn)(Message*);
};

使用游戏对象的代码来接收如下所示的消息:

//if the queue is empty then dont do anything
if (messageQueue.empty())
{
    return;
}

//else grab the front of the queue
Message* newMessage = messageQueue.front();

//pop our message from the queue
messageQueue.pop();

//for each component in our list
for (std::vector<Component*>::iterator i = ComponentList.begin(); i < ComponentList.end(); i++)
{
    Component* itemp = *i;
    //for each message in its listener list
    for (std::vector<Listener*>::iterator j = itemp->Listeners.begin(); j < itemp->Listeners.end(); j++)
    {
        Listener* jtemp = *j;
        //check the listener against the newMessage
        if (jtemp->name == newMessage->name)
        {
            //call jtemp's function
            jtemp->function(newMessage);
        }
    }
}

我遇到的问题是,由于上面的 sn-p 需要调用的函数是组件类型的成员函数,我不能将 Listener.fn 设置为等于 Component::foo 或任何其他函数那件事。

我询问了周围的同学,看看他们是否可以提供任何建议,我收到的两条建议是使用 lambdas 或使用 std::function 将成员函数指针转换为常规函数指针。

我以前从未使用过 lambda 函数,但是在研究了 here 之后,如果我正确掌握它,似乎每次我传递一条违背了目的的消息时我都必须编写一个新的 lambda使用这样的系统。在研究了std::functionhereherehere 之后,似乎std::function 会给我所需的灵活性,但实施却给了我很多错误

我是否忽略了 lambdas 的强大功能,在这种情况下我是否应该使用 std::function,如果是这样,如何创建一个返回 void 并接受消息指针的函数?

【问题讨论】:

  • 您似乎已经找到了回答您自己的问题所需的所有资源。我建议您尝试使用它们,如果您仍然无法解决问题,请向我们提出有关您遇到的错误的具体问题。
  • 无论你使用什么,都无法将成员函数指针转换为普通函数指针。 C++ 没有为这种转换提供任何标准特性。 std::function 和 lambdas 都无法帮助您实现这一目标。你可以切换到使用std::function而不是函数指针,但这意味着你将不得不永远忘记“普通函数指针”。
  • 天啊。请使用基于范围的 for 循环

标签: c++ c++11 pointers lambda


【解决方案1】:

std::function 是正确的存储解决方案。 std::function 存储几乎所有与其签名兼容的东西。

通常你会用 lambda 填充它。因为这比bind 或其他替代方案更容易、更清晰。

std::function<void(Message*)> fn;

fn = [comp](Message * m){ comp->foo(m); };

【讨论】:

    【解决方案2】:

    根据我的经验,如果您可以访问 C++11,请忘记“经典”函数指针。在 C++ 中编写指向成员函数的指针,嗯……很复杂。语法不直观,可能导致脱发:/

    正如 Yakk 所说,std::function 几乎可以在任何情况下工作。 Lambda 表达式虽然在语法上笨拙且微妙 (lambda capture),但非常有用。将它们与std::function 结合起来,你可能会实现你想要的任何东西 x)

    如果你仍然想使用经典的函数指针,我建议你阅读这个帖子(以及这个网站,一般来说,为了其他目的,围绕 C++):
    https://isocpp.org/wiki/faq/pointers-to-members#fnptr-vs-memfnptr-types

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 2014-02-11
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多