【问题标题】:Is this the correct way to implement custom event handlers?这是实现自定义事件处理程序的正确方法吗?
【发布时间】:2011-08-12 19:38:33
【问题描述】:

我正在寻找一种将自定义事件处理程序添加为 c++ 类成员函数的方法。发现这段代码确实有效。 我需要将库类和用户代码分开,允许用户代码自定义库类。 这是代码的概念。这样做是否正确?线程安全性超出了我的问题的范围。编译器是 gcc。 用户代码非常整洁。不使用继承、虚函数、模板

#include <stdio.h>

typedef void fn();

class aaa
{
  public:
  aaa() : customhandler(NULL) {}
  fn *customhandler;
};

//用户代码开始

void dostuff() {
  printf("doing stuff 1\n");
}
void dostuff2() {
  printf("doing stuff 2\n");
}
int main()
{
  aaa aaa1;
  aaa1.customhandler = &dostuff;
  aaa1.customhandler();
  aaa1.customhandler = &dostuff2;
  aaa1.customhandler();
}

【问题讨论】:

  • 如果它可以编译并为您工作,那就没问题了。否则你有什么问题?
  • User code is very very neat & [has] no inheritance, virtual functions, templates used 这两个语句是互斥的。
  • @Als 代码很小:)

标签: c++ event-handling function-pointers


【解决方案1】:

好吧,如果你有一个 Boost 库或支持 C++0x 的编译器,你可能会有这样的代码:

#include <cstdio>
#include <functional>

struct Foo
{
    std::function<void ()> handler;

    void invoke ()
    {
        if (handler)
        {
            handler ();
        }
        else
        {
            printf ("Oops, handler is not there!\n");
        }
    }
};

static void myHandler1 (int arg)
{
    printf ("Handler #1 (arg=%d)\n", arg);
}

static void myHandler2 ()
{
    printf ("Handler #2\n");
}

int main ()
{
    Foo f;

    f.invoke ();

    f.handler = std::bind (&myHandler1, 13);
    f.invoke ();

    f.handler = &myHandler2;
    f.invoke ();
}

它的好处是您可以将函数或仿函数绑定到带有可选附加参数的处理程序。

您的原始代码也可以使用,但如果我想调用类的方法而不是普通函数怎么办?如果我还想传递一些在调用处理程序时可以在处理程序内部访问的状态怎么办?这也是std::function 成为 C++ 标准的众多原因之一。

【讨论】:

  • 自定义函数是静态的。有没有办法让它们成为非静态的?
  • @tohaz:如果函数不是翻译单元的本地函数,则可以删除我的示例中的静态。所以是的,可以在不破坏预期功能的情况下删除静态。
【解决方案2】:

我试过你的代码,它工作正常。 仅供参考,还有另一种编码函数指针的方法。在这种情况下,您的代码可以稍微简化一下。在这里,我对函数指针的 typdef 使用了稍微不同的语法,它可以让你删除 & 符号。

#include "stdafx.h"
#include <stdio.h>

typedef void (*fn)();

class aaa
{
public:
    aaa() : customhandler(NULL) {}
    fn customhandler;
};

void dostuff() {
    printf("doing stuff 1\n");
}
void dostuff2() {
    printf("doing stuff 2\n");
}

int _tmain(int argc, _TCHAR* argv[])
{
    aaa aaa1;
    aaa1.customhandler = dostuff;
    aaa1.customhandler();
    aaa1.customhandler = dostuff2;
    aaa1.customhandler();
    return 0;
}

这两种方法都很好,我只是想告诉你另一种方法。

【讨论】:

    猜你喜欢
    • 2020-01-02
    • 2021-08-10
    • 1970-01-01
    • 2012-11-11
    • 2019-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多