Qt使用signals and slots进行对象通信。 Signals 通常被声明为成员函数,然后Qt MOC生成该函数的定义。
我想了解的是为什么信号不是const成员函数?
编辑: 我希望信号不会修改发件人,这就是问题的原因。
答案 0 :(得分:9)
我希望信号不会修改发件人
信号(如generated by the MOC)不直接修改类实例'成员。但是,生成的代码会传递this
指针,供(潜在)插槽使用。因此,连接的插槽可能会改变信号的发送方。
因此,技术原因是,如果信号为const
,则需要所有插槽实现只调用发送方上的const
类成员,以便编译代码而不会出错。
在代码安全方面,将信号实现为非const
类成员是一个可以理解的决定。在许多情况下,它仍然感觉不自然(例如,如果在同一类中实现的连接槽是const
,或者连接的槽完全属于另一个对象。)
答案 1 :(得分:5)
没有什么可以阻止Qt信号为const AFAIK (使用Qt5.9测试)。 IInspectable 的答案不正确。
以下是我做的测试,表明仍有可能
- 在同一实例中将 const信号连接到非常量插槽
- 在sender()
上调用非常量方法。
我的测试类,编译精细(gcc):
// Stupid class to test the emit of a const-signal
class Test : public QObject
{
Q_OBJECT
public:
// Connect in the constructor from this instance to this instance
explicit Test(QObject *parent = nullptr) : QObject(parent) {
connect(this, &Test::valueChanged, this, &Test::updateString);
}
// To test a non-const method call
void nonConstFoo() {
setObjectName("foo"); // I modify the 'this' instance
}
// To test emit of a non-const signal from a const-method
// void constFoo() const {
// emit fooSignal(); // --> FAIL at compile time
// }
public slots:
void setValue(int value) {
m_value = value;
emit valueChanged(value);
}
void updateString(int value) {
m_string = QString::number(value); // I modify the 'this' instance
nonConstFoo(); // I modify the 'this' instance through a non-const call
auto s = sender();
s->setObjectName("mutated name"); // I modify the 'sender' instance
qDebug() << "Updated string" << m_string;
}
signals:
void valueChanged(int) const; // The signal is const
void fooSignal(); // Non-const signal
private:
int m_value;
QString m_string;
};
以下是MOC为信号生成的代码:
// SIGNAL 0
void Test::valueChanged(int _t1)const
{
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(const_cast< Test *>(this), &staticMetaObject, 0, _a);
}
// SIGNAL 1
void Test::fooSignal()
{
QMetaObject::activate(this, &staticMetaObject, 1, nullptr);
}
我们可以看到Qt在 this 上使用了 const_cast ,所以一切都会正常工作。
在我看来,默认情况下信号不是常数的原因是,这需要MOC在中添加一个const到你的信号(== class-method)定义标题,因此修改您的源代码。
我想这可以通过将每个信号定义包含在宏中来实现,但想象一下编码器和读者的痛苦。我没有看到Qt(你也没有)将你的信号声明为const的任何好处,这对你和Qt来说需要更多的工作。
但是有时您可能需要将它们声明为const。就像你想从const方法发出它们一样。你可以自由地这样做。
答案 2 :(得分:0)
信号可以是const,实际上,如果要从const函数发出信号,则它必须是const信号,但是在插槽端,则不必是const。当用const pures重新实现抽象类时,我不必使用这种可变方法。