【问题标题】:C++ Qt Reflection with Copy and Assignment带有复制和赋值的 C++ Qt 反射
【发布时间】:2011-07-23 06:03:33
【问题描述】:

正如the QObject documentation 和许多其他人所解释的,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;

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

【问题讨论】:

  • 你的意思是不使用QObject。因为反射不是这里问题的根源。问题是 QObject 将复制和赋值设为私有(有充分的理由)。
  • @kristianp,好建议,我会进行编辑 if @alexisdm 没有为我的确切问题提供确切答案。很多时候答案是“不要做你要求做的事”,但在这种情况下,即使这是一个合理的答案,也有一个可以让我做我想做的事:Q_GADGET

标签: c++ qt copy-constructor assignment-operator qobject


【解决方案1】:

如果你只对反思感兴趣

  • 类名,
  • 枚举和标志(Q_ENUMS、Q_FLAGS),
  • 班级信息 (Q_CLASSINFO),

你可以使用Q_GADGET instead of Q_OBJECT:

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

它将声明和定义Foo::staticMetaObject

【讨论】:

  • 哇,我之前没有收到Q_GADGET 的消息。所以它似乎是Q_OBJECT 的一个轻量级和纯静态版本,在某些情况下(像这样)非常有用。遗憾的是没有记录,至少我找不到。这使它成为非官方的,因此不能保证将来可以工作:(
  • @leemes 实际上在QObject 页面上与Q_OBJECT 一起简要提及(我在上面添加了链接)。但你可以说它隐藏得很好,我只是在搜索 moc 源代码时才发现它。
【解决方案2】:

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

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

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

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

【讨论】:

    【解决方案3】:

    我对@9​​87654322@ 了解不多,但如果不允许使用复制构造函数,那么应该是有原因的(在您发布的链接中进行了讨论)。你可以改变你的设计,让它没有。

    如果你坚持,那么memcpy 可能是你最后的选择。我个人不推荐它,因为你必须注意深拷贝、vtable 等,这些并不总是微不足道的。

    【讨论】:

      猜你喜欢
      • 2011-07-26
      • 2012-02-12
      • 1970-01-01
      • 2013-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      相关资源
      最近更新 更多