
在C++中,信号和槽(Signal-Slot)机制是一种用于对象间通信的事件处理机制。它允许一个对象在状态改变时发出信号,而其他对象可以连接这个信号并执行相应的槽函数来响应。这种机制广泛应用于图形界面编程,尤其是Qt框架中。
1. 使用Qt实现信号和槽
Qt是C++中最著名的支持信号和槽机制的框架。它的实现基于元对象系统(Meta-Object System),需要moc(Meta-Object Compiler)预处理。
基本用法示例:
定义带有信号和槽的类:
#include <QObject>
class Sender : public QObject {
Q_OBJECT
public:
Sender() {}
signals:
void valueChanged(int newValue); // 信号
public slots:
void emitSignal(int val) {
emit valueChanged(val); // 发出信号
}
};
class Receiver : public QObject {
Q_OBJECT
public:
Receiver() {}
public slots:
void handleValue(int val) {
printf(“Received: %dn”, val);
}
};
连接信号与槽:
立即学习“C++免费学习笔记(深入)”;
Sender sender;
Receiver receiver;
QObject::connect(&sender, &Sender::valueChanged, &receiver, &Receiver::handleValue);
sender.emitSignal(42); // 输出:Received: 42
说明:
- 使用 Q_OBJECT 宏启用元对象功能
- 信号用 signals: 声明,无需实现
- 槽函数用 public slots:、private slots: 等声明
- connect() 函数建立连接,支持类型检查
- emit 关键字用于触发信号(实际是宏)
2. 不依赖Qt的信号槽实现方式
如果你不想引入Qt,也可以通过现代C++特性自己实现轻量级信号槽机制。
使用std::function和std::vector实现观察者模式:
#include <functional>
#include <vector>
#include <algorithm>
template <typename… Args>
class Signal {
private:
std::vector<std::function<void(Args…)>> slots;
public:
void connect(std::function<void(Args…)> slot) {
slots.push_back(slot);
}
void emit(Args… args) {
for (auto& slot : slots) {
slot(args…);
}
}
};
使用示例:
Signal<int> signal;
signal.connect([](int n) {
printf(“Lambda received: %dn”, n);
});
Struct Handler {
void onEvent(int n) {
printf(“Handler got: %dn”, n);
}
};
Handler h;
signal.connect(std::bind(&Handler::onEvent, &h, std::placeholders::_1));
signal.emit(100); // 触发所有连接的槽
优点:
3. 第三方库选择
除了自己实现,还可以使用成熟的轻量级库:
- Boost.Signals2:线程安全,功能完整,但依赖Boost
- sigc++:GTK+生态使用较多,支持绑定和信号组合
Boost.Signals2 示例:
#include <boost/signals2.hpp>
boost::signals2::signal<void(int)> sig;
sig.connect([](int n){ printf(“%dn”, n); });
sig(42);
总结
信号和槽机制提升了代码解耦性,适合事件驱动场景。Qt提供了最完整的实现,适用于GUI应用;若需轻量化,可用std::function自行实现或选用Boost.Signals2等库。核心思想是将事件发布与处理分离,增强模块灵活性。
基本上就这些,关键是理解“谁发出信号,谁响应”这一模型,再根据项目需求选择合适实现方式。


