这里的问题在于有两个同名的信号:QSpinBox::valueChanged(int)
和 QSpinBox::valueChanged(QString)
。从Qt 5.7开始,提供了帮助函数来选择所需的重载,因此您可以编写以下代码:
connect(spinbox, qOverload<int>(&QSpinBox::valueChanged),
slider, &QSlider::setValue);
对于Qt 5.6及更早版本,您需要将其转换为正确的类型,告诉Qt您想要选择哪一个:
connect(spinbox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
slider, &QSlider::setValue);
我知道,这看起来很丑。但是没有其他办法。今天的课程是:不要过载你的信号和槽!
补充说明:真正让人恼火的是转换操作符:
- 需要重复指定类名。
- 即使返回值通常为
void
(对于信号),也必须指定返回值。
所以,我有时会使用这个C++11片段:
template<typename... Args> struct SELECT {
template<typename C, typename R>
static constexpr auto OVERLOAD_OF( R (C::*pmf)(Args...) ) -> decltype(pmf) {
return pmf;
}
};
使用方法:
connect(spinbox, SELECT<int>::OVERLOAD_OF(&QSpinBox::valueChanged), ...)
我个人认为这并不是很有用。我期望当Creator(或您的IDE)在自动完成获取PMF操作时自动插入正确的转换时,此问题将自行解决。但同时...
注意:基于PMF的连接语法
不需要C++11!
补充2:在Qt 5.7中,添加了帮助函数来缓解此问题,模拟了我的上述解决方法。主要的帮助函数是
qOverload
(还有
qConstOverload
和
qNonConstOverload
)。
使用示例(来自文档):
struct Foo {
void overloadedFunction();
void overloadedFunction(int, QString);
};
qOverload<>(&Foo:overloadedFunction)
qOverload<int, QString>(&Foo:overloadedFunction)
QOverload<>::of(&Foo:overloadedFunction)
QOverload<int, QString>::of(&Foo:overloadedFunction)
补充 3: 如果您查看任何重载信号的文档,现在解决重载问题的方法已经明确地在文档中说明。例如,https://doc.qt.io/qt-5/qspinbox.html#valueChanged-1 中写道:
Note: Signal valueChanged is overloaded in this class. To connect to this signal by using the function pointer syntax, Qt provides a convenient helper for obtaining the function pointer as shown in this example:
connect(spinBox, QOverload<const QString &>::of(&QSpinBox::valueChanged),
[=](const QString &text){ });