可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a class that is a subclass of QObject that I would like to register as a meta-type. The QObject documentation states that the copy-constructor should be private, but the QMetaType documentation states that a type should have a public default constructor, a public copy constructor, and a public destructor.
I can override QObject's private copy constructor and declare a public copy constructor, but is this safe/ok/right?
class MyClass : public QObject { Q_OBJECT public: MyClass(); MyClass(const MyClass &other); ~MyClass(); } Q_DECLARE_METATYPE(MyClass);
回答1:
It is not safe to make a QObject's copy constructor public. You can register a class pointer as the metatype, though. i.e.:
Q_DECLARE_METATYPE(MyClass*);
That's how Qt handles it with QObject and QWidget.
回答2:
What you're asking for is perfectly ok. You can't use QObject
s copy constructor (it's private) in the implementation of your copy constructor, but then again, no-one forces you to:
class MyClass : public QObject { Q_OBJECT public: // ... MyClass( const MyClass & other ) : QObject(), i( other.i ) {} // NOTE: calling QObject default ctor // ... private: int i; };
Depending on what services you need from QObject
, you need to copy some properties over from other
, in both the copy ctor and the copy assignment operator. E.g., if you use QObject for it's dynamic properties feature, you'd need to copy those, too:
MyClass( const MyClass & other ) : QObject(), i( other.i ) { Q_FOREACH( const QByteArray & prop, other.dynamicPropertyNames() ) setProperty( prop.constData(), other.property( prop.constData() ) ); }
Likewise, if you want to maintain signal/slot connections.
回答3:
I use a separate copyValue(const MyClass & other)
function to copy the data members that define the "values" of the MyClass
instance. That ensures that I don't break the assumption of QObject
unique identity, while still being able to duplicate the parts of the class that are defined at compile time.
回答4:
QTFruit fruit; QScriptValue scriptedFruitObject = engine.newQObject(&fruit); engine.globalObject().setProperty("fruit", scriptedFruitObject); engine.setDefaultPrototype(qMetaTypeId(), scriptedFruitObject); QScriptValue qsMetaObject = engine.newQMetaObject(fruit.metaObject()); engine.globalObject().setProperty("eLedState", qsMetaObject); int t = engine.evaluate("eLedState.On").toInteger(); engine.evaluate("fruit.fromJScript(1)"); engine.evaluate("fruit.fromJScript(eLedState.On)"); engine.evaluate("fruit.fromJScript(eLedState.TriState)"); //Create the ctor funtion QScriptValue qsFruitCtor = engine.newFunction(QTFruitConstructor, scriptedFruitObject); //Expose ctor to javascript engine.globalObject().setProperty("QTFruit", qsFruitCtor); //Create the QTFruit object engine.evaluate("var res = new QTFruit()"); engine.evaluate("res.fromJScript(eLedState.TriState)"); class QTFruit : public QObject { Q_OBJECT public: enum eLedState { Off, On , TriState}; Q_ENUMS( eLedState ) QTFruit(); ~QTFruit(); QTFruit( const QTFruit & other ); //QTFruit(const QTFruit& other); public slots: void fromJScript(eLedState state); //void on_inputSpinBox1_valueChanged(int value); //void on_buttonClicked(); // void fromJScript(); //private: }; Q_DECLARE_METATYPE(QTFruit*) Q_DECLARE_METATYPE(QTFruit) QScriptValue QTFruitConstructor(QScriptContext * /* context */, QScriptEngine *interpreter);
回答5:
And the cpp:
QScriptValue QTFruitConstructor(QScriptContext * /* context */, QScriptEngine *interpreter) { //return interpreter->toScriptValue(new QTFruit()); //or return interpreter->toScriptValue(QTFruit()); //but then you need the public copy contructor } QTFruit::QTFruit( const QTFruit & other ) : QObject() { } QTFruit::~QTFruit() { } QTFruit::QTFruit() { } void QTFruit::fromJScript(eLedState state) { int t = 0; }