我可以为QObject的子类复制构造函数吗?

时间:2014-09-17 12:39:25

标签: c++ qt copy-constructor moc copy-assignment

Here我们可以读到没有复制构造和复制赋值运算符可评估。但是here我们可以读到qRegisterMetaTypeQ_DECLARE_METATYPE必须有公共默认构造函数,公共复制构造函数和公共析构函数。问题是:谁说谎?或者我没有正确理解它?

3 个答案:

答案 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::QueuedConnectionQt::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函数。