QObject retunrs with exception even after the copy constructor being declared
-
26-02-2021 - |
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;
}
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.