首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >连接Qt 5中的过载信号和插槽

连接Qt 5中的过载信号和插槽
EN

Stack Overflow用户
提问于 2013-05-28 14:30:46
回答 4查看 71.4K关注 0票数 160

我很难理解Qt 5中新的信号/插槽语法(使用指向成员函数的指针),如新信号时隙语法中所述。我试着改变这个:

代码语言:javascript
复制
QObject::connect(spinBox, SIGNAL(valueChanged(int)),
                 slider, SLOT(setValue(int));

对此:

代码语言:javascript
复制
QObject::connect(spinBox, &QSpinBox::valueChanged,
                 slider, &QSlider::setValue);

但是,当我试图编译它时,我会得到一个错误:

错误:没有调用QObject::connect(QSpinBox*&, <unresolved overloaded function type>, QSlider*&, void (QAbstractSlider::*)(int))的匹配函数

我试过在Linux上使用clang和gcc,都是用-std=c++11

我做错了什么,我该怎么补救?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-05-28 15:18:14

这里的问题是,有两个名称为信号:QSpinBox::valueChanged(int)QSpinBox::valueChanged(QString)。在QT5.7中,提供了一些帮助函数来选择所需的重载,因此您可以编写

代码语言:javascript
复制
connect(spinbox, qOverload<int>(&QSpinBox::valueChanged),
        slider, &QSlider::setValue);

对于Qt5.6和更早版本,您需要通过将Qt转换为正确的类型来告诉Qt您要选择哪一个:

代码语言:javascript
复制
connect(spinbox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
        slider, &QSlider::setValue);

我知道,这是丑陋的。但这是无法避免的。今天的教训是:不要超载你的信号和插槽!

增编:演员们真正烦人的是

  1. 一个重复类名两次。
  2. 一个必须指定返回值,即使它通常是void (对于信号)。

因此,我发现自己有时会使用以下C++11片段:

代码语言:javascript
复制
template<typename... Args> struct SELECT { 
    template<typename C, typename R> 
    static constexpr auto OVERLOAD_OF( R (C::*pmf)(Args...) ) -> decltype(pmf) { 
        return pmf;
    } 
};

用法:

代码语言:javascript
复制
connect(spinbox, SELECT<int>::OVERLOAD_OF(&QSpinBox::valueChanged), ...)

我个人认为这并不是很有用。我希望当Creator (或您的IDE)在自动完成获取PMF的操作时自动插入正确的强制转换时,这个问题就会自行解决。但与此同时..。

注意:基于PMF的连接语法不需要C++11

增编2:在QT5.7中添加了帮助函数来缓解这种情况,这是根据我前面的解决方法建立的。主要的助手是qOverload (您还拥有qConstOverloadqNonConstOverload)。

用法示例(来自文档):

代码语言:javascript
复制
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)

增编3:如果您查看任何重载信号的文档,现在解决重载问题的方法已经在文档本身中清楚地说明了。例如,https://doc.qt.io/qt-5/qspinbox.html#valueChanged-1

注意:信号valueChanged在这个类中重载。为了通过使用函数指针语法连接到此信号,Qt提供了一个方便的助手,用于获取函数指针,如本例所示: 连接(spinBox,QOverload::of(&QSpinBox::valueChanged),={ /* . */ });

票数 292
EN

Stack Overflow用户

发布于 2016-05-18 14:42:44

错误信息是:

错误:没有调用QObject::connect(QSpinBox*&, <unresolved overloaded function type>, QSlider*&, void (QAbstractSlider::*)(int))的匹配函数

其中的重要部分是提到“未解决的重载函数类型”。编译器不知道您指的是QSpinBox::valueChanged(int)还是QSpinBox::valueChanged(QString)

有几种解决重载的方法:

  • connect()提供合适的模板参数 QObject::connect(spinBox,&QSpinBox::valueChanged,slider &QSlider::setValue); 这迫使connect()&QSpinBox::valueChanged解析为接受int的重载。 如果时隙参数有未解决的重载,则需要向connect()提供第二个模板参数。不幸的是,没有语法可以要求第一个被推断,所以您需要同时提供这两个语法。这时,第二种方法可以提供帮助:
  • 使用正确类型的临时变量 void(QSpinBox::*signal)(int) = &QSpinBox::valueChanged;QObject::connect(spinBox,signal,滑块,&QSlider::setValue); 分配给signal将选择所需的重载,现在可以成功地将其替换到模板中。这与“时隙”的论点同样有效,而且我发现在这种情况下,它不那么麻烦。
  • 使用转换 我们可以在这里避免static_cast,因为它只是一种强制,而不是删除语言的保护。我用的是: //还有助于使?:运算符同意的第二次和//第三次论点。template T&& coerce(U& u) {返回u;} 这让我们可以写 连接(spinBox,spinBox滑块,&QSlider::setValue);
票数 16
EN

Stack Overflow用户

发布于 2014-06-07 11:08:45

实际上,您可以用lambda包装您的插槽,如下所示:

代码语言:javascript
复制
connect(spinbox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
    slider, &QSlider::setValue);

会更好看的。*\

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16794695

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档