Qt中5连接过载信号和槽Qt中5连接过载信号和槽(Connecting overloaded sig

2019-05-08 16:06发布

我无法得到认真处理Qt中5新的信号/槽语法(使用指针成员函数),如在新的信号时隙语法 。 我试图改变这样的:

QObject::connect(spinBox, SIGNAL(valueChanged(int)),
                 slider, SLOT(setValue(int));

为此:

QObject::connect(spinBox, &QSpinBox::valueChanged,
                 slider, &QSlider::setValue);

但我得到一个错误,当我尝试编译:

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

我试着铛和gcc在Linux上,都与-std=c++11

我在做什么错了,我怎么能解决这个问题?

Answer 1:

这里的问题是,有两个信号与该名称: 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);

我知道,这是丑陋的 。 但有没有办法解决这个。 今天的教训是: 不要超载信号和槽!


附录 :什么是真正恼人演员是

  1. 一个重复类名的两倍
  2. 一个具有指定返回值,即使它通常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), ...)

我个人觉得这不是真的有用。 我希望这个问题本身消失时,创作者(或您的IDE)自动填充服用的PMF时的操作将自动插入正确的演员。 但是在此期间...

注:基于PMF-CONNECT语法不需要C ++ 11!


附录2:Qt中加入5.7辅助功能,以减轻这一点,我上面的解决方法为蓝本。 主要助手是qOverload (你也有qConstOverloadqNonConstOverload )。

使用实例(从文档):

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)


Answer 2:

该错误消息是:

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

这样做的重要组成部分,是“ 未解决重载函数型 ”的记载。 编译器不知道你是否意味着QSpinBox::valueChanged(int)QSpinBox::valueChanged(QString)

有很多方法来解决超载了一把:

  • 提供一个合适的模板参数connect()

     QObject::connect<void(QSpinBox::*)(int)>(spinBox, &QSpinBox::valueChanged, slider, &QSlider::setValue); 

    这迫使connect()来解决&QSpinBox::valueChanged成需要一个过载int

    如果你有一个插槽的说法没有得到解决重载,那么你就需要提供第二个模板参数来connect() 不幸的是,没有语法要求首先被推断,所以你需要同时提供。 这时候,第二个方法可以帮助:

  • 使用正确类型的临时变量

     void(QSpinBox::*signal)(int) = &QSpinBox::valueChanged; QObject::connect(spinBox, signal, slider, &QSlider::setValue); 

    分配给signal将选择所需的过载,现在它可以成功地被取代到模板中。 这同样适用与“空位”的说法,我觉得在这种情况下那么繁琐。

  • 使用转换

    我们能够避免static_cast在这里,因为它是一个简单的胁迫,而不是去除语言的保护措施。 我用的是这样的:

     // Also useful for making the second and // third arguments of ?: operator agree. template<typename T, typename U> T&& coerce(U&& u) { return u; } 

    这让我们写

     QObject::connect(spinBox, coerce<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), slider, &QSlider::setValue); 


Answer 3:

其实,你可以只是包装用的λ,这您的插槽:

connect(spinbox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
    slider, &QSlider::setValue);

会更好看。 :\



Answer 4:

上述工作的解决方案,但我解决了这一个稍微不同的方式,使用宏,所以以防万一那就是:

#define CONNECTCAST(OBJECT,TYPE,FUNC) static_cast<void(OBJECT::*)(TYPE)>(&OBJECT::FUNC)

在代码中添加这一点。

然后,你的例子:

QObject::connect(spinBox, &QSpinBox::valueChanged,
             slider, &QSlider::setValue);

变为:

QObject::connect(spinBox, CONNECTCAST(QSpinBox, double, valueChanged),
             slider, &QSlider::setValue);


文章来源: Connecting overloaded signals and slots in Qt 5
标签: c++ qt qt5