如何使Qt信号按值发射而不产生编译错误而不是参考



我读到qt中的信号/插槽概念应该始终按值而不是引用传递参数,以确保信号/插槽在线程之间完美工作。

我现在有一段代码,只有当信号的参数是通过引用而不是值发出时才会编译:

#include <QObject>
class mythirdclass {
public:
mythirdclass();
};
class mysecondclass : public QObject, public mythirdclass {
public:
mysecondclass(mythirdclass third);
};
class myclass : public QObject {
Q_OBJECT
public:
myclass();
signals:
// not working
void messageReceived(mysecondclass mymessage);
// working
// void messageReceived(mysecondclass &mymessage);
};
myclass::myclass()
{
mythirdclass third;
mysecondclass msg(third);
emit messageReceived(msg);
}
mysecondclass::mysecondclass(mythirdclass third)
{
// DO stuff
}
mythirdclass::mythirdclass()
{
}

编译器错误为:

..examplemain.cpp: In constructor 'myclass::myclass()':
..examplemain.cpp:28:20: error: use of deleted function 'mysecondclass::mysecondclass(const mysecondclass&)'
emit signal(second);
^
..examplemain.cpp:8:7: note: 'mysecondclass::mysecondclass(const mysecondclass&)' is implicitly deleted because the default definition would be ill-formed:
class mysecondclass : QObject, public mythirdclass {
^

基于我在为mysecondclass编写复制构造函数时考虑的错误,然而,经过一些尝试,我现在放弃了,因为我没有把它做好。

所以我的问题是:

  • 为什么编译首先失败
  • 如果由于缺少复制构造函数而失败,为什么编译器不能隐式定义一个
  • 在我的情况下,工作副本构造函数会是什么样子

提前感谢。

为什么编译首先失败?

因为传递值意味着复制,如果复制构造函数被删除,那么它就不能传递值,并且你的函数不能用这个签名编译,而它可以通过引用接收参数,因为它不涉及复制。

如果因为缺少复制构造函数而失败,为什么编译器不能隐式定义一个?

它实际上失败了,因为它无法隐式定义一个。原因是您的类派生自QObject。而且QObject在设计上没有公共或受保护的副本构造函数。因此编译器不能隐式定义一个。

在我的情况下,工作副本构造函数会是什么样子?

考虑到QObjects的性质,以及当QObjects不可复制时,它背后的设计决策,我建议不要使用占用QObjects的信号和插槽或通过值派生的类(或简单地使用任何这样做的函数,信号/插槽主要是深层次的函数(,而是通过引用或指针。

对于第三个问题,如果您不想为mysecondclass定义默认构造函数,那么您的复制构造函数可能看起来像

mysecondclass(mysecondclass const &other) : mythirdclass() {
/// stuff
}

对于您的第二个问题,我认为(不确定(默认的复制构造函数试图使用已自动删除的默认构造函数,因为您已经从mythirdclass的对象中定义了mysecondclass的另一个构造函数(我建议您在这里对参数使用const引用,以避免无用的副本(

最新更新