#qt #copy-constructor #qobject
#qt #copy-constructor #qobject
Вопрос:
Я пытаюсь написать пример кода для qt script. Я думал, что поступаю правильно, когда объявляю QObjecy
с помощью конструктора копирования, и я также взял на себя смелость объявить =
оператор. Но этот код продолжает выдавать мне
'QObject::QObject' : cannot access private member declared in class 'QObject'
Ошибка.
Я объявляю a, 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 amp;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 amp;in);
static void myClassFromScript(const QScriptValue amp;object, MyClass amp;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 amp;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 amp;object, MyClass amp;out){
out.setId(object.property("id").toInt32());
}
QScriptValue Script_Classes::myClassToScript(QScriptEngine *engine, const MyClass amp;in)
{
QScriptValue value = engine->newObject();
value.setProperty("id", in.id());
return value;
}
Ответ №1:
Проблема в том, что вы не можете скопировать QObject
. Из QObject
документации:
У QObject нет ни конструктора копирования, ни оператора присваивания. Это сделано специально. На самом деле, они объявлены, но в закрытом разделе с помощью макроса Q_DISABLE_COPY(). Фактически, все классы Qt, производные от QObject (прямые или косвенные), используют этот макрос, чтобы объявить свои конструктор копирования и оператор присваивания закрытыми. Обоснование приведено в обсуждении Identity vs Value на странице объектной модели Qt.
Основным следствием этого является то, что вам следует использовать указатели на 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
=
operator не является общедоступным. Что вам нужно сделать, чтобы добиться копирования данных, так это сделать это вручную :
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(amp;a1);
Если вам интересно, почему QObject
не разрешает присваивание, прочитайте часть документации по объектной модели, посвященную идентификатору и значению.
Комментарии:
1. Здравствуйте, большое вам спасибо за быстрый ответ. Я все еще в замешательстве. вы сказали, что «Вы должны использовать указатели на QObject». Я думал, что это то, что я делал, объявляя «MyClass (QObject * aparent = 0);» Не так ли. Пожалуйста, поделитесь со мной и приведите простой пример или укажите мне на простой пример по этому вопросу. Я пробовал поискать в Google по этому вопросу, и все говорит то же самое, что вы предлагаете, но я не понимаю, как это сделать на практике. Перегрузка = была отчаянной мерой для реализации конструктора копирования, поскольку в нем говорилось, что он не предусмотрен в QObject.
2. Я не знаю, как вас благодарить. Это больше, чем справка.. Большое вам спасибо…