Question

I am trying to write a sample code for qt script. I thought I am doing the right thing when I declare the QObjecy with the copy construtor and I also took the liberty to declare the = operator. But this code keeps giving me the

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

Error.

I am declaring a MyClass which is a QObject as follows. I am aware of the fact that this can some one see what I am doing a wroing here.

The header:

#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

And my source class is as follows:

#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;
}
Was it helpful?

Solution

The problem is that you cannot copy a QObject. From the QObject documentation:

QObject has neither a copy constructor nor an assignment operator. This is by design. Actually, they are declared, but in a private section with the macro Q_DISABLE_COPY(). In fact, all Qt classes derived from QObject (direct or indirect) use this macro to declare their copy constructor and assignment operator to be private. The reasoning is found in the discussion on Identity vs Value on the Qt Object Model page.

The main consequence is that you should use pointers to QObject (or to your QObject subclass) where you might otherwise be tempted to use your QObject subclass as a value. For example, without a copy constructor, you can't use a subclass of QObject as the value to be stored in one of the container classes. You must store pointers.

Also QObject has not the == implemented so you cannot compare two instance of your class.

PS What is the point of overloading the = operator and making it operate like the == one? This makes your code obfuscated and debugging much more complex.

EDIT

Assume you have the following simple class inheriting from QObject

class A : public QObject
{
     Q_OBJECT
public:
     int anInt;
     double aDouble;
}

Assume now that you want to create two inctances of A somewhere in your code.

A a1;
A a2;

It is illegal to call a1=a2 since QObject's = operator is not public. What you need to do in order to achieve the copying of the data is to do it manually :

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

On the other hand if you used pointers it is totally legal to point at the same object

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

Now both a1 and a2 point at the same memory location and have the same data. If you want to have two different objects you could create a constructor with argument a pointer to the object. For our simple class you could have:

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

and now it is legal do:

A a1;
A a2(&a1);

If you wonder why QObject does not allow assignment read the Identity vs Value part of the Object Model documentation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top