gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 16:30:52 26 4
gpt4 key购买 nike

这里是 C++ 新手。我在读A Deeper Look at Signals and Slots ,它声称 1) 回调本质上是类型不安全的,以及 2) 为了使它们安全,您需要在函数周围定义一个纯虚类包装器。我很难理解为什么这是真的。例如,这是 Qt 在其 tutorial page for signals and slots 上提供的代码:

// Header file
#include <QObject>

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 <functional>
#include <vector>

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

int value() const { return m_value; }
std::vector<std::function<void(int)>> 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 版本更短,despite them claiming that it's not .除了 Counter 之外,它没有定义任何新类。它仅使用标准库代码,不需要特殊的编译器 (moc) 即可工作。那么,为什么信号和槽优先于回调呢? C++11 是否简单地废弃了这些概念?

谢谢。

最佳答案

两者之间有一个巨大的区别:线程。

传统回调总是在调用线程的上下文中调用。信号和槽则不然——只要线程正在运行一个事件循环(如果它是一个QThread)槽就可以在任何线程中。

当然,您可以通过回调手动完成所有这些操作——多年来我编写了许多 Win32 应用程序,这些应用程序使用 Windows 风格的消息泵来处理跨线程的回调——但它有很多样板代码而不是编写、维护或调试非常有趣。

关于c++ - 为什么信号和槽比普通的旧回调更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34237190/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com