【问题标题】:Call member function when class type is not known类类型未知时调用成员函数
【发布时间】:2014-10-24 16:20:24
【问题描述】:

我想要一个可以将回调设置为指向成员函数的指针的类。这意味着我需要存储函数的地址和对象实例的地址。该函数应具有正确的原型并返回回调所期望的值。

我玩过 std::mem_fnboost::bind(使用 Boost Signals2 库),但似乎我必须知道包含回调函数的类的类型才能存储这些信息。

似乎应该有一种方法来存储一对指向任何对象/函数的void*,但这显然闻起来很有趣,失去了类型安全性等等。

给定一个类SomeClass 和一个方法some_method,我希望能够做这样的事情:

SomeClass obj;
some_other_class.set_callback(&SomeClass::some_method, &obj);

以下是我使用 Boost 完成此任务的方法。请注意,这使用了 Boost 信号,对于简单的回调来说似乎有点过分了。此外,存在使用“组合器”来确定回调的返回值的信号问题,因为可能有多个插槽连接到单个信号。我只需要支持一个回调。另请注意,这是一个完整的可编译程序:

#define _SCL_SECURE_NO_WARNINGS

#include <iostream>
#include <boost/bind.hpp>
#include <boost/signals2.hpp>
#include <string>

using namespace std;

struct MessageSource
{
    boost::signals2::signal<void(const string &)> send_message;
    typedef boost::signals2::signal<void(const string &)>::slot_type slot_type;

    template<typename A, typename B>
    boost::signals2::connection connect(A a, B b)
    {
        return send_message.connect(boost::bind(a, b, _1));
    }

    void send_msg(const string& msg)
    {
        send_message(msg);
    }
};

struct Printer
{
    void print(const string& msg) { std::cout << msg << std::endl; };
};

int main()
{
    {
        Printer p;
        MessageSource s;
        s.connect(&Printer::print, &p);
        s.send_msg("test");
    }

    system("pause");
    return 0;
}

我认为这里的神奇之处在于boost::bind() 能够为其第一个参数处理多种类型。我只是不明白它如何在不知道类型的情况下在某种私有字段中保留它...

在这种情况下,函子真的是正确的解决方案吗?好像成员函数用起来方便多了……

【问题讨论】:

  • 如果你可以访问 C++11,你可以使用 std::function&lt;void(const std::string &amp;)&gt;[p] (const std::string &amp; m) { p.print(m); }

标签: c++ boost callback pointer-to-member


【解决方案1】:

根据上面 cdhowie 的评论,我能够使用std::functionstd::bind 提出以下解决方案:

#include <iostream>
#include <string>
#include <functional>

using namespace std;

struct MessageSource
{
    function<void(const string& msg)> _callback;

    template<typename A, typename B>
    void connect(A func_ptr, B obj_ptr)
    {
        _callback = bind(func_ptr, obj_ptr, placeholders::_1);
    }

    void send_msg(const string& msg)
    {
        if (_callback)
            _callback(msg);
    }

    void disconnect()
    {
        _callback = nullptr;
    }
};

struct Printer
{
    void print(const string& msg) { std::cout << msg << std::endl; };
};

int main()
{
    {
        Printer p;
        MessageSource s;
        s.connect(&Printer::print, &p);
        s.send_msg("test");
        s.disconnect();
        s.send_msg("test again");
    }

    system("pause");
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 2011-12-12
    相关资源
    最近更新 更多