【问题标题】:how to pass a member function as a function pointer?如何将成员函数作为函数指针传递?
【发布时间】:2010-08-04 02:33:23
【问题描述】:

我想为工人类添加一个记录器功能, 如何将成员函数作为函数指针传递? 使用 mem_fun?

这里是代码示例:

class Work{
public:
    void (*logger) (const string &s);
    void do_sth(){if (logger) logger("on log")};
};

classs P{
public:
    void log(const string &s)(cout << s);
};

int main(){
    Work w;
    P p;
    w.logger = &p.log;
    w.do_sth();
}

编辑:

我不想使用 void (P::*xxx)() 因为它坚持 P 类...

我知道C++ hide sth,真正的日志函数是:void log(P &p, const string &s),

而真正的项目是这样的:

我创建了一个CDialog,并且有一个日志功能,它将日志字符串复制到一个CEdit。

所以我需要把这个日志函数传递给一个 Worker 类,这个类做一些串口工作,

我需要记录并显示发送和接收的数据...

【问题讨论】:

  • 我认为这是一种很常见的设计模式。

标签: c++


【解决方案1】:

您可以使用std::functionstd::bind 完成此操作:

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

class Work {
public:
    std::function<void(const std::string&)> logger;
    void do_sth() { logger("on log"); }
};

class P {
public:
    void log(const std::string& s) { std::cout << s; }
};

int main() {
    Work w;
    P p;
    w.logger = std::bind(&P::log, p, std::placeholders::_1);
    w.do_sth();
}

请注意,functionbind 可能还没有在您的实现的标准库中;你也可以get them from the Boost libraries

【讨论】:

  • @James McNellis,不应该将std::placeholders::_1 改为std::tr1::placeholders::_1 吗?
  • 在我的真实项目中,我使用(并编译好): using namespace std; device.logger = boost::bind(&CDeviceTesterDlg::logger, this, _1);
  • @Praetorian:这取决于你从哪里得到bind。各种较旧的实现在命名空间std::tr1 中有它和相关的名称,这是TR1 库扩展规范中为它们指定的位置;最新的标准库版本在命名空间 std 中具有名称,这是在(即将发布的)C++0x 标准中指定它们的位置。
  • @linjunhalida:为了维护您的代码的任何人,请不要使用using namespace std;。没有充分的理由使用它,它只会造成麻烦。
  • 我接受这个建议,为什么不使用 using namespace std?有讨论链接吗?
【解决方案2】:

唯一的方法是作为一个静态函数。不幸的是,静态函数不绑定到单个对象,而是类的全局函数。如果幸运的话,采用函数指针的函数也将采用 void*,您可以使用它来绑定到原始对象 - 您的静态函数可以将其转换回对象指针并调用对象上的另一个函数做实际的工作。

【讨论】:

    【解决方案3】:

    这需要闭包,而 C++ 并不完全具备。您可以制作函子并使用模板,但您必须采取一些措施。

    【讨论】:

    • @linjunhalida:James McNellis 打败了我。他的回答更好。
    猜你喜欢
    • 1970-01-01
    • 2013-06-29
    • 2015-12-11
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    • 2017-03-17
    相关资源
    最近更新 更多