2009-06-05 5 views
9

Ich habe eine Klasse, die eine Unterklasse von QObject ist, die ich als Meta-Typ registrieren möchte. Die QObject documentation besagt, dass der Kopierkonstruktor privat sein sollte, aber die QMetaType documentation besagt, dass ein Typ einen öffentlichen Standardkonstruktor, einen öffentlichen Kopierkonstruktor und einen öffentlichen Destruktor haben sollte.Unterklasse von QObject, qRegisterMetaType und der Konstruktor der privaten Kopie

Ich kann den privaten Kopierkonstruktor von QObject überschreiben und einen öffentlichen Kopierkonstruktor deklarieren, aber ist das sicher/ok/richtig?

class MyClass : public QObject { 
    Q_OBJECT 
    public: 
    MyClass(); 
    MyClass(const MyClass &other); 
    ~MyClass(); 
} 
Q_DECLARE_METATYPE(MyClass); 
+1

So wie ich werde am Ende ist QSharedPointer (Qt 4.5 und höher) zu verwenden. Q_DECLARE_METATYPE (QSharedPointer ) – darkadept

Antwort

16

Es ist nicht sicher, den Kopierkonstruktor eines QObjects öffentlich zu machen. Sie können jedoch einen Klassenzeiger als Metatyp registrieren. d. h .:

Q_DECLARE_METATYPE (MyClass *);

So behandelt Qt es mit QObject und QWidget.

5

Was Sie fragen, ist vollkommen in Ordnung. Sie nicht QObject s Copy-Konstruktor verwenden können (es ist privat) in der Umsetzung Ihrer Copykonstruktor, aber dann wieder, niemand zwingt Sie zu:

class MyClass : public QObject { 
    Q_OBJECT 
public: 
    // ... 
    MyClass(const MyClass & other) 
     : QObject(), i(other.i) {} // NOTE: calling QObject default ctor 
    // ... 
private: 
    int i; 
}; 

Je nachdem, welche Leistungen Sie von QObject benötigen, müssen Sie Kopieren Sie einige Eigenschaften über other, sowohl in der Kopie ctor und der Kopie Zuweisung Operator. Zum Beispiel, wenn Sie QObject verwenden es die dynamischen Eigenschaften des Feature, müssen Sie diejenigen kopieren, auch:

MyClass(const MyClass & other) 
     : QObject(), i(other.i) 
    { 
     Q_FOREACH(const QByteArray & prop, other.dynamicPropertyNames()) 
      setProperty(prop.constData(), other.property(prop.constData())); 
    } 

Ebenso, wenn Sie Signal/Slot-Verbindungen pflegen wollen.

+0

Richtig, das macht Sinn. Es ist also möglich, muss aber sehr sorgfältig codiert werden. – darkadept

0

Ich verwende eine separate copyValue(const MyClass & other) Funktion, um die Datenelemente zu kopieren, die die "Werte" der MyClass Instanz definieren. Das stellt sicher, dass ich die Annahme QObject eindeutiger Identität nicht durchbrich, während ich immer noch die Teile der Klasse duplizieren kann, die zur Kompilierzeit definiert wurden.

0
QTFruit fruit; 
QScriptValue scriptedFruitObject = engine.newQObject(&fruit); 
engine.globalObject().setProperty("fruit", scriptedFruitObject); 

engine.setDefaultPrototype(qMetaTypeId<QTFruit>(), 
           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); 
+0

Und der cpp: QScriptValue QTFruitConstructor (QScriptContext */* Kontext * /, QScriptEngine * Interpreter) { \t // Rückkehr Interpreter-> ToScriptValue (neue QTFruit()); \t // oder \t Rückkehrinterpreter-> toScriptValue (QTFruit()); // aber dann müssen Sie die öffentliche Kopie contructor } QTFruit :: QTFruit (const QTFruit & andere) : QObject() { } QTFruit :: ~ QTFruit() { } QTFruit: : QTFruit() { } Leere QTFruit :: fromJScript (eLedState Zustand) { \t int t = 0; } –

0

Und die cav:

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; 
} 
+0

Willkommen bei StackOverflow. Wenn Sie Ihrer vorherigen Antwort etwas hinzufügen möchten, können Sie sie bearbeiten. Wenn Sie schon dabei sind, möchten Sie vielleicht auch Ihrem Code eine Erklärung hinzufügen. – void