当前位置:  开发笔记 > 编程语言 > 正文

为什么信号和插槽比普通的旧回调更好?

如何解决《为什么信号和插槽比普通的旧回调更好?》经验,为你挑选了1个好方法。

这里有新手到C++.我正在阅读更深入的信号和插槽,它声称1)回调本质上是类型不安全的,2)为了使它们安全,你需要在你的函数周围定义一个纯虚拟类包装器.我很难理解为什么这是真的.作为一个例子,这里是Qt在其教程页面上提供的信号和插槽的代码:

// Header file
#include 

class Counter : public QObject
{
    Q_OBJECT

public:
    Counter() { m_value = 0; }

    int value() const { return m_value; }

public slots:
    void setValue(int value);

signals:
    void valueChanged(int newValue);

private:
    int m_value;
};

// .cpp file
void Counter::setValue(int value)
{
    if (value != m_value) {
        m_value = value;
        emit valueChanged(value);
    }
}

// Later on...
Counter a, b;
QObject::connect(&a, SIGNAL(valueChanged(int)),
                 &b, SLOT(setValue(int)));

a.setValue(12);     // a.value() == 12, b.value() == 12
b.setValue(48);     // a.value() == 12, b.value() == 48

这是使用回调重写的代码:

#include 
#include 

class Counter
{
public:
    Counter() { m_value = 0; }

    int value() const { return m_value; }
    std::vector> valueChanged;

    void setValue(int value);

private:
    int m_value;
};

void Counter::setValue(int value)
{
    if (value != m_value) {
        m_value = value;
        for (auto func : valueChanged) {
            func(value);
        }
    }
}

// Later on...
Counter a, b;
auto lambda = [&](int value) { b.setValue(value); };
a.valueChanged.push_back(lambda);

a.setValue(12);
b.setValue(48);

正如您所看到的,回调版本是类型安全的并且比Qt版本更短,尽管它们声称它不是.除了之外,它没有定义任何新类Counter.它仅使用标准库代码,不需要特殊的编译器(moc)即可工作.那么,为什么信号和插槽比回调更受欢迎?C++ 11是否完全废弃了这些概念?

谢谢.



1> MrEricSir..:

这两者之间存在巨大差异:线程.

传统的回调总是在调用线程的上下文中调用.信号和插槽不是这样 - 只要线程正在运行事件循环(如果它是a QThread),则插槽可以在任何线程中.

当然,您可以通过回调手动完成所有这些操作 - 多年来我编写了许多Win32应用程序,这些应用程序使用的是Windows风格的消息泵,可以跨越线程来处理回调 - 但它是很多样板代码而且没什么好玩的.编写,维护或调试.

推荐阅读
围脖上的博博_771
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有