Nothing prevents a Qt signal to be const AFAIK (用Qt5.9测试) . IInspectable的答案是不正确的 .
下面是我做的测试,表明它仍然可以
将const信号连接到同一实例中的非const插槽
在 sender() 上调用非const方法 .
我的测试类,编译精细(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;
};
3 回答
信号(如generated by the MOC)不直接修改类实例的成员 . 但是,生成的代码会传递一个
this
指针,供(潜在)插槽使用 . 因此,连接的插槽可以改变信号的发送方 .因此技术原因是,如果信号是
const
,则需要所有插槽实现只调用发送方上的const
类成员,以便编译代码而不会出错 .在代码安全方面,将信号实现为非
const
类成员是一个可以理解的决定 . 在许多情况下,它仍然感觉不自然(例如,如果在同一类中实现的连接槽是const
,或者连接的槽完全属于另一个对象) .Nothing prevents a Qt signal to be const AFAIK (用Qt5.9测试) . IInspectable的答案是不正确的 .
下面是我做的测试,表明它仍然可以
sender()
上调用非const方法 .我的测试类,编译精细(gcc):
以下是MOC为信号生成的代码:
我们可以看到Qt在此使用const_cast,所以一切都会正常工作 .
在我看来,默认情况下信号不是const的原因是这需要MOC在 your 标头中为 your signal(== class-method)定义添加一个const,因此修改你的源代码 .
我想通过在宏中包含每个信号定义是可行的,但想象编码器和读者的痛苦 . 我没有看到Qt(也不是你)将你的信号声明为const的任何好处,这将需要你和Qt的更多工作 .
But 您可能需要将它们声明为const . 就像你想从const方法发出它们一样 . 你可以自由地这样做 .
信号可以是const,实际上如果你想从const函数发出一个信号,它必须是一个const信号,但在槽端,它不需要是const . 当我用const pures重新实现抽象类时,我已经不必这样使用mutable了 .