QObject retunrs с исключением даже после объявления конструктора копирования - PullRequest
0 голосов
/ 11 ноября 2011

Я пытаюсь написать пример кода для скрипта qt. Я думал, что поступаю правильно, когда объявляю QObjecy с копировщиком, и я также позволил себе объявить оператор =. Но этот код продолжает давать мне

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

Error.

Я объявляю 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 Ответ

8 голосов
/ 11 ноября 2011

Проблема в том, что вы не можете скопировать QObject. Из QObject документации:

QObject не имеет ни конструктора копирования, ни оператора присваивания. Это по замыслу. На самом деле они объявлены, но в частном раздел с макросом Q_DISABLE_COPY (). На самом деле, все классы Qt полученный из QObject (прямой или косвенный), используйте этот макрос для объявления их конструктор копирования и оператор присваивания должны быть частными. рассуждения можно найти в обсуждении Identity vs Value на Qt Страница объектной модели.

Основным следствием является то, что вы должны использовать указатели на QObject (или ваш подкласс QObject), где вы могли бы в противном случае использовать ваш подкласс QObject как значение. Например, без копии конструктор, вы не можете использовать подкласс QObject в качестве значения хранится в одном из контейнерных классов. Вы должны хранить указатели.

Также QObject не реализовал ==, поэтому вы не можете сравнить два экземпляра вашего класса.

PS Какой смысл перегрузить оператор = и заставить его работать как ==? Это делает ваш код запутанным и отладочным намного сложнее.

EDIT

Предположим, у вас есть следующий простой класс, наследующий от 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;

Теперь и a1, и a2 указывают на одну и ту же ячейку памяти и имеют одинаковые данные. Если вы хотите иметь два разных объекта, вы можете создать конструктор с аргументом указатель на объект. Для нашего простого класса вы можете иметь:

A::A(A* a)
{
   anInt = a->anInt;
   aDouble = a->aDouble;
}

и теперь законно делать:

A a1;
A a2(&a1);

Если вам интересно, почему QObject не позволяет присваивать, прочитайте часть Идентичность против значения документации по объектной модели.

...