Могу ли я иметь конструктор копирования для подкласса QObject?

Вот мы можем прочитать, что нет конструкции копирования и копирования оператора присваивания оценивается. Но Вот мы можем прочитать это qRegisterMetaType а также Q_DECLARE_METATYPE должен иметь открытый конструктор по умолчанию, открытый конструктор копирования и открытый деструктор. Вопрос в том, кто лжет? Или я не правильно понял?

3

Решение

Все верно
1. QObject не может быть скопировано, и все его потомки также не могут быть скопированы.
2. Q_DECLARE_METATYPE принимает объекты с открытым конструктором, конструктором копирования и деструктором.

Там нет противоречия, потому что вы не можете зарегистрироваться QObject потомки с Q_DECLARE_METATYPE,

РЕДАКТИРОВАТЬ:

Когда вы конвертируете свой класс в QVariant он использует конструктор копирования, чтобы сделать копию вашего объекта:

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

Другие решения

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 зарегистрировать указатели на объекты QObjects. Например:

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

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

Указатели — это типы POD, которые можно создавать, копировать и т. Д.

2

Вы, безусловно, можете реализовать конструктор копирования и операторы присваивания в классе, производном от QObject, но вы не можете ссылаться на удаленный конструктор копирования базового класса и оператор присваивания. Вы должны свернуть свой собственный.

Таким образом, вам необходимо учитывать тот факт, что конструкция или назначение копирования не будут влиять на соединения сигнал / слот с исходным или целевым объектом. Вы также должны решить, как обрабатывается происхождение при копировании — любой из трех возможных вариантов является совершенно произвольным — поэтому в большинстве случаев копировать объекты не имеет смысла, он слишком подвержен ошибкам.

Например, используя идиома копирования и обмена.

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 функция для производных классов.

1