QObject
コピーできないからといって、クラスをコピーしたり、割り当てたりするときにコピーする必要があるわけではありません。具体的には、QObjectのコピーおよび割り当て演算子からクラスを分離するだけです(削除されるため)。)。
通常、「コピー可能非コピー可能QObject」を別のクラスに除外します。
// main.cpp
#include <QObject>
#include <QVariant>
class CopyableQObject : public QObject
{
protected:
explicit CopyableQObject(QObject* parent = nullptr) : QObject(parent) {}
CopyableQObject(const CopyableQObject& other) { initFrom(other); }
CopyableQObject(CopyableQObject&& other) { initFrom(other); }
CopyableQObject& operator=(const CopyableQObject& other)
{
return initFrom(other), *this;
}
CopyableQObject& operator=(CopyableQObject&& other)
{
return initFrom(other), *this;
}
private:
void initFrom(const CopyableQObject& other)
{
setParent(other.parent());
setObjectName(other.objectName());
}
void initFrom(CopyableQObject& other)
{
initFrom(const_cast<const CopyableQObject&>(other));
for (QObject* child : other.children())
child->setParent( this );
for (auto& name : other.dynamicPropertyNames())
setProperty(name, other.property(name));
}
};
QObject
インスタンス間で必要な属性をコピーできます。上記では、親とオブジェクトの名前がコピーされています。さらに、別のオブジェクトから移動すると、その子の親が変更され、動的プロパティ名も転送されます。
これで、CopyableQObject
アダプターは、派生クラスをコピー構築可能、コピー割り当て可能、移動構築可能、および移動割り当て可能にするすべてのコンストラクターを実装します。
クラスが行う必要があるのは、上記のアダプタクラスから派生することだけです。
class MyClass : public CopyableQObject
{
Q_OBJECT
public:
Q_SIGNAL void signal1();
Q_SIGNAL void signal2();
};
それが機能することをテストできます。
int main()
{
int counter = 0;
MyClass obj1;
MyClass obj2;
Q_SET_OBJECT_NAME(obj1);
QObject::connect(&obj1, &MyClass::signal1, [&]{ counter += 0x1; });
QObject::connect(&obj1, &MyClass::signal2, [&]{ counter += 0x10; });
QObject::connect(&obj2, &MyClass::signal1, [&]{ counter += 0x100; });
QObject::connect(&obj2, &MyClass::signal2, [&]{ counter += 0x1000; });
Q_ASSERT(counter == 0);
emit obj1.signal1();
emit obj1.signal2();
Q_ASSERT(counter == 0x11);
QObject obj3(&obj1);
Q_ASSERT(obj3.parent() == &obj1);
const auto name1 = obj1.objectName();
obj2 = std::move(obj1);
Q_ASSERT(obj3.parent() == &obj2);
Q_ASSERT(obj2.objectName() == name1);
emit obj2.signal1();
emit obj2.signal2();
Q_ASSERT(counter == 0x1111);
}
#include "main.moc"
これで、コンパイル可能な完全な例は終わりです。