C++ Qt 反射与复制和赋值

发布于 2024-11-25 18:58:10 字数 666 浏览 1 评论 0原文

作为QObject文档< /a> 和许多其他人解释说,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;

在这种情况下允许复制和赋值的最佳方法是什么?我绝对需要编写复制构造函数和赋值运算符吗?他们会是什么样子?反思还会起作用吗?

As the QObject documentation and many others explain, a QObject has an identity and thus hides its copy constructor and assignment operator.

However, I'm not deriving from QObject for its dynamic properties feature or the signals/slots feature. I only want reflection, or the ability to access 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)

I then can't copy Foo with:

Foo a;
Foo b;
a = b;

What's the best way to allow copy and assignment in this case? Do I absolutely need to write a copy constructor and assignment operator? What would they look like? Will reflection still work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风轻花落早 2024-12-02 18:58:10

如果您只对

  • 类名、
  • 枚举和标志(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

If you are only interested in having reflection for

  • the class name,
  • enums and flags (Q_ENUMS, Q_FLAGS),
  • class info (Q_CLASSINFO),

you can use Q_GADGET instead of Q_OBJECT:

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

which will declare and define Foo::staticMetaObject.

没有伤那来痛 2024-12-02 18:58:10

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

#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!。当基类将其复制构造函数/复制赋值运算符声明为私有时,这不会阻止派生类实现自己的版本。它只是阻止派生类调用基类版本

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

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

You can certainly implement both a copy constructor and a copy assignment operator in your derived class, but it's likely a sign of bad design. Take this example:

#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;
}

This will compile just fine. However, as expected, when you run the resulting program, all that is printed is Derived copy constructor invoked!. When the base class declares its copy constructor/copy assignment operator as private, that doesn't prevent derived classes from implementing their own versions. It simply prevents derived classes from calling the base class versions.

And therein lies the problem: it's always good practice to make sure you copy all parts of an object, so that you indeed have two distinct copies. Part of your object includes the data owned by the base class, so you should always make sure to invoke the base class's copy constructor/copy assignment operator to ensure that a full copy is made. But that data is by design non-copyable. Thus, it is impossible to copy all parts of the object.

It's up to you if you want to stick with this design. One important thing to ask yourself is, does your derived class really need to be copyable at all? If not, then there's nothing to worry about!

迷迭香的记忆 2024-12-02 18:58:10

我对 qt 了解不多,但如果不允许复制构造函数,那么应该有一个原因(在您发布的链接中对此进行了讨论)。您可以更改您的设计以不拥有它。

不过,如果您坚持,那么 memcpy 可以是您的最后的手段。我个人并不推荐它,因为你必须关心深度复制、虚表等,这些并不总是微不足道的。

I don't know much about qt, but if the copy constructor is not allowed then there should be a reason for it (which is discussed in the link you posted). You can change your design not to have it.

Still if you insist then memcpy can be your last resort. I don't recommend it personally, because you have to take care about deep copying, vtable etc. which are not always trivial.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文