【问题标题】:Compiler picks wrong overloaded function编译器选择错误的重载函数
【发布时间】:2018-04-16 11:51:31
【问题描述】:

我即将使我的源代码适应 Qt 中的新信号和插槽语法。虽然以下代码在使用已弃用的 const char* signal 参数时运行良好,但它不适用于新的 QMetaMethod &signal 语法。

class SignalWaiter : public QObject {
    Q_OBJECT
public:
    SignalWaiter(const QObject* sender, const QMetaMethod &signal);

private slots:
    void signalCaught();
};

SignalWaiter::SignalWaiter(const QObject* sender, const QMetaMethod &signal) {
    QObject::connect(sender, signal, this, &SignalWaiter::signalCaught);
}

void SignalWaiter::signalCaught() {
}

编译器在connect() 命令处停止并显示以下消息:

错误:C2664:'QMetaObject::Connection QObject::connect(const QObject *,const char *,const char *,Qt::ConnectionType) const':无法将参数 2 从 'const QMetaMethod' 转换为 'const char *'

没有可以执行此转换的用户定义转换运算符,或者无法调用该运算符

很明显,编译器尝试使用旧语法调用重载的连接方法。我做错了什么?

【问题讨论】:

  • 编译器是对的——const QMetaMethod &signal 不是你假设的函数(信号)指针。
  • @vahancho 嗯?编译器错误说它需要一个const char*(这也不是一个函数指针)
  • 从历史上看,Qt 使用了 SIGNAL 宏,其评估为 const char*

标签: c++ qt signals-slots


【解决方案1】:

connect() you're trying to use 有签名:

QMetaObject::Connection QObject::connect(
    const QObject *sender, 
    const QMetaMethod &signal,
    const QObject *receiver,
    const QMetaMethod &method,
    Qt::ConnectionType type = Qt::AutoConnection)

注意第 4th 参数 const QMetaMethod &method 不是指向成员的指针,这就是您收到错误的原因。

要进行适当的转换,您可以使用:

auto metaSlot = metaObject()->method(metaObject()->indexOfSlot("signalCaught()"));
QObject::connect(sender, signal, this, metaSlot);

尽管正如@p-a-o-l-o 所指出的,新的信号/槽语法使用指向成员函数的指针,而不是QMetaMethod。他的解决方案可能正是您真正想要的。

【讨论】:

  • 但是SignalWaiter::signalCaught 不是信号。
【解决方案2】:

我认为 O'Neil 的答案解决了编译问题,但如果 OP 真的想要

使我的源适应新的信号和槽语法

也许他们想给SignalWaiter 类另一个构造函数,像这样:

template<typename T>
SignalWaiter(const T* sender, void (T::* signal)())
{
    QObject::connect(sender, signal, this, &SignalWaiter::signalCaught);
}

有一个带有void mysignal() 信号的MyClass 类:

MyClass * myclass = new MyClass();
SignalWaiter * waiter = new SignalWaiter(myclass, &MyClass::mysignal);

【讨论】:

    【解决方案3】:

    变化

    QObject::connect(sender, signal, this, &SignalWaiter::signalCaught);
    

    QObject::connect(sender, signal, this, QMetaMethod::fromSignal(&SignalWaiter::signalCaught));
    

    为我工作,这与 O'Neil 的答案相似,但在语法方面更短一些。请注意,您还需要在 QMetaMethod::fromSignal() 命令中的每个构造函数调用中包装信号参数。

    p-a-o-l-o 提出的解决方案对我不起作用,因为我的 SignalWaiter 类实际上继承自 QObject,它禁止使用模板。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-02
      • 1970-01-01
      • 2016-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多