即使在声明了复制构造函数之后,QObject 也会返回异常

Posted

技术标签:

【中文标题】即使在声明了复制构造函数之后,QObject 也会返回异常【英文标题】:QObject retunrs with exception even after the copy constructor being declared 【发布时间】:2011-11-11 16:06:00 【问题描述】:

我正在尝试为 qt 脚本编写示例代码。当我用复制构造器声明QObjecy 时,我认为我做对了,我还冒昧地声明了= 运算符。但是这段代码一直给我

'QObject::QObject' : cannot access private member declared in class 'QObject'

错误。

我声明一个MyClass,它是一个QObject,如下所示。我知道这样一个事实,有人可以看到我在这里做错了什么。

标题:

#ifndef SCRIPT_CLASSES_H
#define SCRIPT_CLASSES_H
#include "QObject"
#include "QtScript/QScriptValue"
#include "QtScript/QScriptable"
#include "QtScript/QScriptClass"

class MyClass : public QObject

    Q_OBJECT
//    Q_PROPERTY( int _id WRITE setId READ id )
public :
    MyClass(QObject *aparent =0) ;
    ~MyClass();

//     bool operator =(MyClass obj);

public slots:
    void setId(int d);
    int id() const ;
//    bool MyClass::equals(const MyClass &other);
private :
    int _id;
;

class QScriptEngine;
class Script_Classes : public QObject, public QScriptClass

public:
    Script_Classes(QScriptEngine *engine);
    ~Script_Classes();
private :
    static QScriptValue myClassToScript(QScriptEngine *engine,const MyClass &in);
    static void myClassFromScript(const QScriptValue &object, MyClass &out);
;

#endif // SCRIPT_CLASSES_H

而我的源码类如下:

#include "script_classes.h"
#include "QMetaType"
#include "QtScript/QScriptEngine"
#include "QtScript/QScriptValue"

Q_DECLARE_METATYPE(MyClass)
Q_DECLARE_METATYPE(MyClass*)

MyClass::MyClass(QObject *aparent) : QObject (aparent)

MyClass::~MyClass()

void MyClass::setId(int d)
    _id = d;



int MyClass::id() const
   return _id;


bool MyClass::equals(const MyClass &other)

    return id() == other.id();


bool MyClass::operator =(MyClass obj)
    return id()==obj.id();




Script_Classes::Script_Classes(QScriptEngine *engine):QObject(engine),QScriptClass(engine)

    qScriptRegisterMetaType<MyClass>(engine, myClassToScript, myClassFromScript);
    MyClass testClass(this);


void Script_Classes::myClassFromScript(const QScriptValue &object, MyClass &out)
out.setId(object.property("id").toInt32());


QScriptValue Script_Classes::myClassToScript(QScriptEngine *engine, const  MyClass &in)    

    QScriptValue value = engine->newObject();
    value.setProperty("id", in.id());
    return value;

【问题讨论】:

【参考方案1】:

问题是您无法复制QObject。来自QObject 文档:

QObject 既没有复制构造函数也没有赋值运算符。 这是设计使然。实际上,它们是声明的,但是在私有的 带有宏 Q_DISABLE_COPY() 的部分。事实上,所有的 Qt 类 派生自 QObject(直接或间接)使用此宏声明 他们的复制构造函数和赋值运算符是私有的。这 在 Qt 上关于 Identity vs Value 的讨论中可以找到推理 对象模型页面。

主要结果是 你应该使用指向 QObject 的指针(或 您的 QObject 子类),否则您可能会想使用 您的 QObject 子类作为值。 例如,没有副本 构造函数,不能使用 QObject 的子类作为值 存储在容器类之一中。您必须存储指针。

另外QObject 没有实现==,所以你不能比较你的类的两个实例。

PS 重载= 运算符并使其像== 一样运行有什么意义?这会使您的代码混淆和调试更加复杂。

编辑

假设你有以下从QObject继承的简单类

class A : public QObject

     Q_OBJECT
public:
     int anInt;
     double aDouble;

现在假设您想在代码中的某处创建两个 A 整数。

A a1;
A a2;

调用a1=a2 是非法的,因为QObject's = 运营商不是公开的。为了实现数据的复制,您需要做的是手动完成:

a2.anInt = a1.anInt
a2.aDouble = a1.aDouble

另一方面,如果你使用指针,指向同一个对象是完全合法的

A* a1 = new A;
A* a2 = new A;
a1 = a2;

现在a1a2 都指向同一个内存位置并拥有相同的数据。如果你想拥有两个不同的对象,你可以创建一个构造函数,参数是指向对象的指针。对于我们的简单类,您可以:

A::A(A* a)

   anInt = a->anInt;
   aDouble = a->aDouble;

现在是合法的:

A a1;
A a2(&a1);

如果您想知道为什么 QObject 不允许赋值,请阅读对象模型文档的 Identity vs Value 部分。

【讨论】:

您好,非常感谢您的快速回复。我仍然很困惑。你说“你应该使用指向 QObject 的指针”。我以为这就是我在声明“MyClass(QObject *aparent =0);”时所做的事情是不是。请告诉我,给我一个简单的例子,或者给我一个简单的例子。我试过用谷歌搜索,一切都和你的建议一样,但我不明白如何在实践中做到这一点。重载 = 是实现复制构造函数的绝望措施,因为它表示 QObject 中没有提供它。 我不知道该怎么感谢你。这不仅仅是一个帮助......非常感谢......

以上是关于即使在声明了复制构造函数之后,QObject 也会返回异常的主要内容,如果未能解决你的问题,请参考以下文章

即使使用复制构造函数,克隆对象也会更改原始对象[重复]

为啥我能够为 QObject 子类创建复制构造函数并重载赋值运算符?

Qt中QObject中的parent参数

[QT入门篇]3 QObject的拷贝构造函数与赋值运算符

即使只有主函数,在主函数外部声明变量也会改变输出

Qt构造函数的参数:QObject *parent = Q_NULLPTR