Can I create a constructor for a QObject subclass?

Here we can read that no copy operator and copy assignment operator can be evaluated. But here we can read that qRegisterMetaType

and Q_DECLARE_METATYPE

must have a public default constructor, the constructor public copies and a public destructor. The question is, who is telling the lie? Or did I not understand it correctly?

+3


source to share


3 answers


That's right:
1. QObject

cannot be copied, and all of its descendants also cannot be copied. 2. Q_DECLARE_METATYPE

accepts objects with a public constructor, copy constructor and destructor.

There is no contradiction because you cannot register descendants QObject

with Q_DECLARE_METATYPE

.

EDIT:



When you convert your class to QVariant

, it uses the copy constructor to create a copy of your object:

 void *ptr = QMetaType::construct(x->type, copy);

      

+4


source


Macro

Q_DECLARE_METATYPE

is used to generate information for custom user types if you want to use them as SIGNAL / SLOT arguments.

Example:

struct MyInfo
{
  QString name;
  QDate birthday;
};

Q_DECLARE_METATYPE( MyInfo )

// ... somewhere in cpp:
{
  QObject::connect( obj1, SIGNAL( newData( MyInfo ), SLOT( onNewData( MyInfo ) ) );
}

      

Without a macro, Q_DECLARE_METATYPE

you couldn't pass MyInfo

a signal or slot as an argument.

If you are using cross-stream connections ( Qt::QueuedConnection

, Qt::BlockingQueuedConnection

etc.), you also need to register your type when called qRegisterMetatype<MyInfo>();

.




But it's okay to use Q_DECLARE_METATYPE

POINTERS to register with QObjects. For example:

class MyItem
  : public QObject
{
  Q_OBJECT
//...
};

Q_DECLARE_METATYPE( MyItem * )
// or event better Q_DECLARE_METATYPE( QSharedPointer< MyItem > )

      

Pointers are POD types that can be created, copied, etc.

+2


source


You can, of course, implement the copy constructor and assignment operators in the class that derives from QObject

, but you cannot refer to the remote base class copy constructor and assignment operator. You need to roll yourself.

So you have to live with the fact that constructing or assigning a copy will not affect the signal / slot connections to either the source or the target. You also have to decide how the parent copy is handled when copying - any of the three possible choices are completely arbitrary - so in most cases there is no point in copying objects, this is also error prone.

For example, using the 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;
  }
};

      

Note that you need to override the function swap

for derived classes.

+1


source







All Articles