Here我们可以读到没有复制构造和复制赋值运算符可评估。但是here我们可以读到qRegisterMetaType
和Q_DECLARE_METATYPE
必须有公共默认构造函数,公共复制构造函数和公共析构函数。问题是:谁说谎?或者我没有正确理解它?
答案 0 :(得分:5)
一切都是真的:
1. QObject
无法复制,其所有后代也无法复制。
2. Q_DECLARE_METATYPE
接受具有公共构造函数,复制构造函数和析构函数的对象。
没有矛盾,因为您无法使用QObject
注册Q_DECLARE_METATYPE
个后代。
编辑:
将类转换为QVariant
时,它会使用复制构造函数制作对象的副本:
void *ptr = QMetaType::construct(x->type, copy);
答案 1 :(得分:2)
Q_DECLARE_METATYPE
宏用于为自定义用户类型生成信息,如果您想将它们用作SIGNAL / SLOT参数。
示例:
struct MyInfo
{
QString name;
QDate birthday;
};
Q_DECLARE_METATYPE( MyInfo )
// ... somewhere in cpp:
{
QObject::connect( obj1, SIGNAL( newData( MyInfo ), SLOT( onNewData( MyInfo ) ) );
}
如果没有Q_DECLARE_METATYPE
宏,则无法将MyInfo
作为信号或插槽参数传递。
如果您使用跨线程连接(Qt::QueuedConnection
,Qt::BlockingQueuedConnection
等),则还需要通过qRegisterMetatype<MyInfo>();
电话注册您的类型。
但是可以使用Q_DECLARE_METATYPE
将POINTERS注册到QObjects。例如:
class MyItem
: public QObject
{
Q_OBJECT
//...
};
Q_DECLARE_METATYPE( MyItem * )
// or event better Q_DECLARE_METATYPE( QSharedPointer< MyItem > )
指针是POD类型,可以构造,复制等。
答案 2 :(得分:1)
您当然可以在派生自QObject
的类中实现复制构造函数和赋值运算符,但不能引用已删除的基类复制构造函数和赋值运算符。你需要自己动手。
因此,您需要考虑到复制结构或赋值不会影响与源或目标对象的信号/插槽连接这一事实。您还必须决定在复制时如何处理父母 - 三种可能的选择中的任何一种都是完全随意的 - 这就是为什么在大多数情况下复制对象没有意义,这太容易出错。
例如,使用copy-and-swap idiom。
class CopyableObject : public QObject
{
Q_OBJECT
public:
friend void swap(CopyableObject & first, CopyableObject & second) {
// d_ptr swap doesn't take care of parentage
QObject * firstParent = first.parent();
QObject * secondParent = second.parent();
first.setParent(0);
second.setParent(0);
first.d_ptr.swap(second.d_ptr);
second.setParent(firstParent);
first.setParent(secondParent);
}
CopyableObject(const CopyableObject & other) : QObject(other.parent()) {
Q_ASSERT(thread() == other.thread());
setObjectName(other.objectName());
blockSignals(other.signalsBlocked());
}
CopyableObject(QObject * parent = 0) : QObject(parent) {}
// C++11 only
#if __cplusplus >= 201103L
CopyableObject(CopyableObject && other) : CopyableObject() {
swap(*this, other);
}
#endif
CopyableObject & operator=(CopyableObject other) {
swap(*this, other);
return *this;
}
};
请注意,您需要为派生类重新实现swap
函数。