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

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

成都创新互联公司专注为客户提供全方位的互联网综合服务,包含不限于网站建设、网站设计、鲤城网络推广、重庆小程序开发公司、鲤城网络营销、鲤城企业策划、鲤城品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;成都创新互联公司为所有大学生创业者提供鲤城建站搭建服务,24小时服务热线:18982081108,官方网址:www.cdcxhl.com

问题代码:

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);
};

定义了两个信号:

  • loginResult() 这个信号采用 eResult 作为参数,而 eResult 是 Sender 类内部定义的类型;

  • otherSignal() 作为参照,使用Qt所定义的类型的信号。

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不成功的原因是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注创新互联网站,小编会继续努力为大家带来更多实用的文章!


网页名称:Qtsignal函数使用类内部类型作为参数导致connect不成功的原因是什么
标题来源:http://azwzsj.com/article/jjgedg.html