問題描述
我無(wú)法掌握 Qt 5 中的新信號(hào)/插槽語(yǔ)法(使用指向成員函數(shù)的指針),如 新的信號(hào)槽語(yǔ)法.我試著改變這個(gè):
I'm having trouble getting to grips with the new signal/slot syntax (using pointer to member function) in Qt 5, as described in New Signal Slot Syntax. I tried changing this:
QObject::connect(spinBox, SIGNAL(valueChanged(int)),
slider, SLOT(setValue(int));
為此:
QObject::connect(spinBox, &QSpinBox::valueChanged,
slider, &QSlider::setValue);
但是當(dāng)我嘗試編譯它時(shí)出現(xiàn)錯(cuò)誤:
but I get an error when I try to compile it:
錯(cuò)誤:沒有匹配的函數(shù)調(diào)用QObject::connect(QSpinBox*&,<未解析的重載函數(shù)類型>, QSlider*&, void(QAbstractSlider::*)(int))
error: no matching function for call to
QObject::connect(QSpinBox*&, <unresolved overloaded function type>, QSlider*&, void (QAbstractSlider::*)(int))
我在 Linux 上嘗試過使用 clang 和 gcc,都使用 -std=c++11
.
I've tried with clang and gcc on Linux, both with -std=c++11
.
我做錯(cuò)了什么,我該如何解決?
What am I doing wrong, and how can I fix it?
推薦答案
這里的問題是有兩個(gè)具有該名稱的信號(hào):QSpinBox::valueChanged(int)
和 QSpinBox::valueChanged(QString)
代碼>.從 Qt 5.7 開始,提供了幫助函數(shù)來(lái)選擇所需的重載,因此您可以編寫
The problem here is that there are two signals with that name: QSpinBox::valueChanged(int)
and QSpinBox::valueChanged(QString)
. From Qt 5.7, there are helper functions provided to select the desired overload, so you can write
connect(spinbox, qOverload<int>(&QSpinBox::valueChanged),
slider, &QSlider::setValue);
對(duì)于 Qt 5.6 及更早版本,您需要通過將其轉(zhuǎn)換為正確的類型來(lái)告訴 Qt 您想要選擇哪一個(gè):
For Qt 5.6 and earlier, you need to tell Qt which one you want to pick, by casting it to the right type:
connect(spinbox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
slider, &QSlider::setValue);
我知道,它丑陋.但是沒有辦法解決這個(gè)問題.今天的教訓(xùn)是:不要讓信號(hào)和槽過載!
I know, it's ugly. But there's no way around this. Today's lesson is: do not overload your signals and slots!
附錄:演員陣容真正令人討厭的是
Addendum: what's really annoying about the cast is that
- 一個(gè)重復(fù)兩次類名
- 即使返回值通常是
void
(對(duì)于信號(hào)),也必須指定返回值.
- one repeats the class name twice
- one has to specify the return value even if it's usually
void
(for signals).
所以我發(fā)現(xiàn)自己有時(shí)會(huì)使用這個(gè) C++11 代碼片段:
So I've found myself sometimes using this C++11 snippet:
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), ...)
我個(gè)人覺得它不是很有用.我希望當(dāng) Creator(或您的 IDE)在自動(dòng)完成獲取 PMF 的操作時(shí)自動(dòng)插入正確的演員表時(shí),這個(gè)問題會(huì)自行消失.但與此同時(shí)...
I personally find it not really useful. I expect this problem to go away by itself when Creator (or your IDE) will automatically insert the right cast when autocompleting the operation of taking the PMF. But in the meanwhile...
注意:基于 PMF 的連接語(yǔ)法不需要 C++11!
Note: the PMF-based connect syntax does not require C++11!
附錄 2:在 Qt 5.7 中添加了輔助函數(shù)來(lái)緩解這種情況,以我上面的解決方法為模型.主要的幫手是 qOverload
(你我也有 qConstOverload
和 qNonConstOverload
).
Addendum 2: in Qt 5.7 helper functions were added to mitigate this, modelled after my workaround above. The main helper is qOverload
(you've also got qConstOverload
and qNonConstOverload
).
使用示例(來(lái)自文檔):
Usage example (from the docs):
struct Foo {
void overloadedFunction();
void overloadedFunction(int, QString);
};
// requires C++14
qOverload<>(&Foo:overloadedFunction)
qOverload<int, QString>(&Foo:overloadedFunction)
// same, with C++11
QOverload<>::of(&Foo:overloadedFunction)
QOverload<int, QString>::of(&Foo:overloadedFunction)
<小時(shí)>
附錄 3:如果您查看任何重載信號(hào)的文檔,現(xiàn)在文檔本身清楚地說明了重載問題的解決方案.例如,https://doc.qt.io/qt-5/qspinbox.html#valueChanged-1 說
Addendum 3: if you look at the documentation of any overloaded signal, now the solution to the overloading problem is clearly stated in the docs themselves. For instance, https://doc.qt.io/qt-5/qspinbox.html#valueChanged-1 says
注意:信號(hào) valueChanged 在此類中被重載.為了使用函數(shù)指針語(yǔ)法連接到這個(gè)信號(hào),Qt 提供了一個(gè)方便的助手來(lái)獲取函數(shù)指針,如下例所示:
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){ /* ... */ });
這篇關(guān)于在 Qt 5 中連接過載的信號(hào)和插槽的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!