带有复制和赋值的c++ Qt反射

C++ Qt Reflection with Copy and Assignment

本文关键字:c++ Qt 反射 赋值 复制      更新时间:2023-10-16

正如QObject文档和其他许多文档所解释的那样,QObject有一个标识,因此隐藏了它的复制构造函数和赋值操作符。

然而,我不是因为QObject的动态属性特征或信号/插槽特征而派生的。我只想要反射,或者访问Foo::staticMetaObject的能力。

class Foo : public QObject {
    Q_OBJECT
    Q_ENUMS(Color)
public:
    enum Color { Blue, Red, Pink };
private:
    Color color;
};
Q_DECLARE_METATYPE(Foo::Color)

我不能复制Foo:

Foo a;
Foo b;
a = b;

在这种情况下,允许复制和赋值的最佳方式是什么?我一定要写一个复制构造函数和赋值操作符吗?它们会是什么样子?反射还能起作用吗?

如果您只对

的反射感兴趣
  • 类名,
  • 枚举和标志(Q_ENUMS, Q_FLAGS),
  • 类信息(Q_CLASSINFO),

你可以用Q_GADGET代替Q_OBJECT:

class Foo {
    Q_GADGET
    Q_ENUMS(Color)
public:
    enum Color { Blue, Red, Pink };
private:
    Color color;
};

将声明和定义Foo::staticMetaObject

当然可以在派生类中同时实现复制构造函数和复制赋值操作符,但这可能是设计不良的标志。举个例子:

#include <iostream>
class Base {
public:
    Base() {}
private:
    Base(const Base& other) {
        std::cout << "Base copy constructor invoked!" << std::endl;
    }
};
class Derived : public Base {
public:
    Derived() {}
    Derived(const Derived& other) {
        std::cout << "Derived copy constructor invoked!" << std::endl;
    }
};
int main(int argc, char** argv) {
    Derived a;
    Derived b = a;
    return 0;
}

可以很好地编译。然而,正如预期的那样,当您运行结果程序时,输出的全部内容是Derived copy constructor invoked!。当基类将其复制构造函数/复制赋值操作符声明为私有时,这并不妨碍派生类实现它们自己的版本。它只是防止派生类调用基类版本

问题就在这里:确保复制对象的所有部分总是好的做法,这样你就确实有了两个不同的副本。对象的一部分包含基类拥有的数据,因此您应该始终确保调用基类的复制构造函数/复制赋值操作符,以确保进行完整的复制。但这些数据被设计为不可复制的。因此,不可能复制对象的所有部分。

如果你想坚持这个设计,这取决于你。你要问自己的一个重要问题是,你的派生类真的需要可复制吗?如果没有,那就没什么好担心的!

我不太了解qt,但如果不允许复制构造函数,那么应该有一个原因(在你发布的链接中讨论)。你可以改变你的设计,不包含它。

如果你坚持,那么memcpy可能是你最后的选择。我个人不建议这样做,因为你必须注意深度复制,虚表等,这些并不总是微不足道的。