Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

发布时间:2021-10-26 15:58:01 作者:iii
来源:亿速云 阅读:261

这篇文章主要介绍“Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么”,在日常操作中,相信很多人在Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

问题代码:

sender.h

class Sender : public QObject
{
  Q_OBJECT
  public:
    explicit Sender(QObject *parent = nullptr);
    enum eResult {
      kSuccess,
      kFail,
    };
  signals:
    void loginResult(eResult result);
    void otherSignal(QString str);
};

定义了两个信号:

receiver.h

class Receiver : public QObject
{
    Q_OBJECT
  public:
    explicit Receiver(QObject *parent = nullptr);

  signals:
  public slots:
    void onLoginResult(Sender::eResult result);
    void onOtherSignal(QString str);

  private:
    Sender *sender_;
};

在 Receiver 中定义了两个slot分别接收 Sender 的两个信号。

在 Receiver 的构造函数中:

Receiver::Receiver(QObject *parent)
  : QObject(parent)
  , sender_(new Sender())
{
  connect(sender_, SIGNAL(loginResult(Sender::eResult)), this, SLOT(onLoginResult(Sender::eResult)));
  connect(sender_, SIGNAL(otherSignal(QString)), this, SLOT(onOtherSignal(QString)));
}

结果在运行时报错:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

提示信号没有连接上。

如果我们将 eResult 放到 Sender 类外面,则没有这个问题。

这是为什么呢?

是不是只要是类内部的类型都会出错?

为了排除是我们自定义的枚举的原因,我们把自己定义的 eResult 改成 MyString,其它也对应改过来。

再试:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

结果还是报错:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

这也证定了我的猜想。为是什么呢?

打开自动生成的 moc_sender.cpp 文件看看里面的内容:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

如果我们再加一个signal:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

moc_sender.cpp 中会发生什么样的变化呢?

(1)字面量里多出两个新的字面量。

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

(2)在 qt_meta_data_Sender 中也多出些新的描述:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

可以看出,qt_meta_data_Sender 中可以描述出一个 QObject 类有哪些信号函数。每个信号函数的返回类型与参数各为什么。

从上可以看到,qt_meta_data_Sender 中记录的信号自定义的参数类型idx指向的是 MyString。我们在 Receiver 中 connect() 使用的是 Sender::MyString。会不会是两者对不上号导致的呢?

如果我们改成这样:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

把 Sender:: 前缀加上。

看看会不会成功了呢?结果没有再报错了。

我们再来看看 moc_sender.cpp 的变化:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

猜想:

在下面的 connect() 代码中:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

SIGNAL() 宏把  Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么 预编译成 "loginResult(Sender::MyString)" 的字符串。在执行时,就会拿着该字串去 Sender 对象中找信号名为 "loginResult" 参数个数只有一个,参数类型名为 "Sender::MyString" 的信号进行连接。

如果我们在 Sender 中将 loginResult 信号的参数类型写成 MyString 而不是写全 Sender::MyString,那么在 connect() 时,它就不能在 Sender 的 qt_meta_data_Sender 中找到这个信号,所以就失败了。

如果我们还是采用原来的做法:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

而在 connect() 的地方,直接写 MyString,而不写成 Sender::MyString,如下:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

执行报错:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

说是不兼容的参数类型。

可能 connect() 函数在入口处,就对参数signal与slot的参数类型字串进行比较,如果不一致,那么就会认为错误。

那反过来,我们在 connect() 时将 slot 的参数写成:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

执行结果:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

如果我们把 Receive::onLoginResult() 的参数类型改成 MyString 呢?

如下:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么 

编译通过,运行时 connect() 正常。

是不是它只认类型的名称,不做类型推导呢?

我们大胆地做一个尝试:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

我们给 MyString 乱指定一个类型。

结果编译通过,运行时 connect() 正常。

从本质上 MyString 就是 QString 的别名。

如果在 Receive 端使用 QString 替代 MyString 是不是就不能 connect() 成功了呢?

如下修改:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

编译正常,运行结果:

Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么

这个实验足于证明,connect() 只管类型名称的比效,完全不做任何的类型推导。

综上结论:

在执行 QObject::connect() 时,它会对signal与slot参数的名称进行对比,只有名称完会一致的才能连接上,否会不失败。

值得注意的是:它只管对类型的名称进行比较,完全不会做任何的类型推导与类型检查。

到此,关于“Qt signal函数使用类内部类型作为参数导致connect不成功的原因是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

推荐阅读:
  1. QT之消息处理(七)
  2. QT多线程深入分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c++

上一篇:Python嵌入C的相关操作方案是怎么样的

下一篇:Python GUI开发工具中五种类型分别是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》