如何使 Qt Signal 按值发出而不产生编译错误而不是引用?
How to make Qt Signal emit by value without compile errors instead of reference?
我读到 qt 中的 signal/slot 概念应该始终按值而不是引用传递参数,以确保 signals/slots 在线程之间完美地工作。
我现在有一段代码,只有当信号的参数是通过引用而不是值发出时才会编译:
#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()
{
}
编译器错误是:
..\example\main.cpp: In constructor 'myclass::myclass()':
..\example\main.cpp:28:20: error: use of deleted function 'mysecondclass::mysecondclass(const mysecondclass&)'
emit signal(second);
^
..\example\main.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
编写复制构造函数,但是经过一些尝试后我暂时放弃了,因为我没有做对。
所以我的问题是:
- 为什么首先编译失败?
- 如果由于缺少复制构造函数而失败,为什么编译器不能隐式定义一个?
- 在我的案例中,工作副本构造函数会是什么样子?
提前致谢。
对于你的第三个问题,如果你不想为 mysecondclass 定义默认构造函数,你的复制构造函数可能看起来像
mysecondclass(mysecondclass const &other) : mythirdclass() {
/// stuff
}
关于你的第二个问题,我想(不确定)默认复制构造函数尝试使用已自动删除的默认构造函数,因为你已经从 mythirdclass 的对象定义了另一个 mysecondclass 的构造函数(我建议你在这里为参数使用 const 引用以避免无用的复制)
Why is the compiling failing in the first place?
因为按值传递意味着复制,如果复制构造函数被删除,那么它就不能按值传递,你的函数不能用这个签名编译,但它可以通过引用接收它的参数,因为它不涉及复制。
If it fails because of a missing copy constructor, why is the compiler not able to define one implicitly?
它实际上失败了,因为它无法隐式定义一个。原因是您的 class 派生自 QObject
。而且 QObject
doesn't have a public or protected copy-constructor,是设计使然。所以编译器不能隐式定义一个。
How would the working copy constructor in my case look like?
鉴于 QObject
s 的性质,以及涉及 QObject
s 不可复制时背后的设计决策,我建议不要使用采用 [=10] 的信号和插槽=]s 或 class 按值从它派生(或者只是执行此操作的任何函数,而 signals/slots 主要是深层函数),而是通过引用或指针。
我读到 qt 中的 signal/slot 概念应该始终按值而不是引用传递参数,以确保 signals/slots 在线程之间完美地工作。
我现在有一段代码,只有当信号的参数是通过引用而不是值发出时才会编译:
#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()
{
}
编译器错误是:
..\example\main.cpp: In constructor 'myclass::myclass()':
..\example\main.cpp:28:20: error: use of deleted function 'mysecondclass::mysecondclass(const mysecondclass&)'
emit signal(second);
^
..\example\main.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
编写复制构造函数,但是经过一些尝试后我暂时放弃了,因为我没有做对。
所以我的问题是:
- 为什么首先编译失败?
- 如果由于缺少复制构造函数而失败,为什么编译器不能隐式定义一个?
- 在我的案例中,工作副本构造函数会是什么样子?
提前致谢。
对于你的第三个问题,如果你不想为 mysecondclass 定义默认构造函数,你的复制构造函数可能看起来像
mysecondclass(mysecondclass const &other) : mythirdclass() {
/// stuff
}
关于你的第二个问题,我想(不确定)默认复制构造函数尝试使用已自动删除的默认构造函数,因为你已经从 mythirdclass 的对象定义了另一个 mysecondclass 的构造函数(我建议你在这里为参数使用 const 引用以避免无用的复制)
Why is the compiling failing in the first place?
因为按值传递意味着复制,如果复制构造函数被删除,那么它就不能按值传递,你的函数不能用这个签名编译,但它可以通过引用接收它的参数,因为它不涉及复制。
If it fails because of a missing copy constructor, why is the compiler not able to define one implicitly?
它实际上失败了,因为它无法隐式定义一个。原因是您的 class 派生自 QObject
。而且 QObject
doesn't have a public or protected copy-constructor,是设计使然。所以编译器不能隐式定义一个。
How would the working copy constructor in my case look like?
鉴于 QObject
s 的性质,以及涉及 QObject
s 不可复制时背后的设计决策,我建议不要使用采用 [=10] 的信号和插槽=]s 或 class 按值从它派生(或者只是执行此操作的任何函数,而 signals/slots 主要是深层函数),而是通过引用或指针。