2014-09-17 2 views
3

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

+0

Не могли бы вы предоставить любую ситуацию, когда вам необходимо зарегистрировать класс класса QObject в качестве метатипа? Документация в порядке. –

+0

Вам не нужно регистрировать QObject или его подкласс с помощью qRegisterMetaType. – vahancho

+0

'qRegisterMetaType' регистрирует определенные пользователем типы, а не те, которые получены из QObject –

ответ

4

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

Нет никаких противоречий, поскольку вы не можете зарегистрировать QObject потомков с Q_DECLARE_METATYPE.

EDIT:

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

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

Но почему мой класс должен иметь copy-constructor для работы как QObject? Я имею в виду хранение в QVariant. – VALOD9

+3

Да, чтобы храниться в 'QVariant', ваш класс должен иметь конструктор копирования, но он не работает как QObject, потому что QObject, QWidget ... не может быть сохранен в' QVariant' – Ezee

+0

Добавлено объяснение о конструкторе копирования к ответу. – Ezee

1

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, которые могут быть построены, скопированные и т.д.

0

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

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

Например, используя 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 для производных классов.

Смежные вопросы