仅仅因为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"
完整的、可编译的示例到此结束。