2

我一直在研究一些信号/插槽的实现,它们毫无例外都非常复杂,有些甚至依赖于 MOC 和额外的代码生成,比如 Qt 的那些。

我意识到存在诸如威胁安全之类的问题,但是对于一个简单的单线程场景,采用简单的方法是否有问题,例如:

typedef void (*fPtr)();

class GenericButton
{
public:
    GenericButton() : funcitonToCall(nullptr) {}
    void setTarget(fPtr target) {
        funcitonToCall = target;
    }

    void pressButton() {
        if (funcitonToCall) funcitonToCall();
    }

private:
    fPtr funcitonToCall;
};

void doSomething(){
    std::cout << "doing something..." << std::endl;
}

void doSomethingElse(){
    std::cout << "doing something else..." << std::endl;
}

int main(){
    GenericButton myButton;
    myButton.setTarget(doSomething);
    myButton.pressButton();
    myButton.setTarget(doSomethingElse);
    myButton.pressButton();
}

仍然可以链接其他几个方法并在目标 void 函数中传递数据。那么,为什么在单击按钮时执行一些代码这样微不足道的事情会变得如此复杂。

4

1 回答 1

2

这是一个非常明智的解决方案,但不要仅限于函数指针。使用std::function它可以让你绑定东西、调用对象的成员函数、使用 lambdas 并且仍然在有意义的地方使用函数指针。例子:

#include <iostream>
#include <functional>

using namespace std::placeholders;


class GenericButton
{
public:
    typedef std::function<void()> fPtr;
    GenericButton() : funcitonToCall(nullptr) {}
    void setTarget(fPtr target) {
        funcitonToCall = target;
    }

    void pressButton() {
        if (funcitonToCall) funcitonToCall();
    }

private:
    fPtr funcitonToCall;
};

struct foo {
    void doSomething() const {
        std::cout << "doing something in a foo..." << std::endl;
    }

    static void alternative(int i) {
        std::cout << "And another, i=" << i << "\n";
    }
};

void doSomethingElse() {
    std::cout << "doing something else..." << std::endl;
}

int main() {
    GenericButton myButton;
    foo f;
    myButton.setTarget(std::bind(&foo::doSomething, &f));
    myButton.pressButton();
    myButton.setTarget(doSomethingElse);
    myButton.pressButton();
    myButton.setTarget(std::bind(foo::alternative, 666));
    myButton.pressButton();
    myButton.setTarget([](){ std::cout << "Lambda!\n"; });
    myButton.pressButton();
}

C++ 中几乎总是有比函数指针更好的解决方案。

如果您没有std::function/std::bind总是有替代方案来促进这项工作,您可以推出自己的std::function替代方案而无需太多工作,如果您想做这样的事情,这将是值得的。

大多数现有的信号/槽机制都可以追溯到诸如此类的事情boost::bind不可行的时候。那些日子已经一去不复返了,您可以获得一些标准和更灵活的东西,而不仅仅是一个函数指针。

于 2012-09-20T15:55:11.217 回答