Вот мы можем прочитать, что нет конструкции копирования и копирования оператора присваивания оценивается. Но Вот мы можем прочитать это qRegisterMetaType
а также Q_DECLARE_METATYPE
должен иметь открытый конструктор по умолчанию, открытый конструктор копирования и открытый деструктор. Вопрос в том, кто лжет? Или я не правильно понял?
Все верно
1. QObject
не может быть скопировано, и все его потомки также не могут быть скопированы.
2. Q_DECLARE_METATYPE
принимает объекты с открытым конструктором, конструктором копирования и деструктором.
Там нет противоречия, потому что вы не можете зарегистрироваться QObject
потомки с Q_DECLARE_METATYPE
,
РЕДАКТИРОВАТЬ:
Когда вы конвертируете свой класс в QVariant
он использует конструктор копирования, чтобы сделать копию вашего объекта:
void *ptr = QMetaType::construct(x->type, copy);
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, которые можно создавать, копировать и т. Д.
Вы, безусловно, можете реализовать конструктор копирования и операторы присваивания в классе, производном от 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
функция для производных классов.