7

正如文档和许多其他人所解释的那样, a具有QObjectQObject标识,因此隐藏了它的复制构造函数和赋值运算符。

但是,我并不是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;

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

4

3 回答 3

14

如果你只对反思感兴趣

  • 班级名称,
  • 枚举和标志(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.

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

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

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

于 2011-08-26T00:21:52.390 回答
1

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

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

于 2011-07-23T06:15:27.180 回答