2009-06-05 5 views
9

J'ai une classe qui est une sous-classe de QObject que je souhaite enregistrer en tant que méta-type. Le QObject documentation indique que le constructeur de copie doit être privé, mais le QMetaType documentation indique qu'un type doit avoir un constructeur public par défaut, un constructeur de copie publique et un destructeur public.Sous-classe de QObject, qRegisterMetaType et le constructeur de copie privée

Je peux remplacer le constructeur de copie privée de QObject et déclarer un constructeur de copie publique, mais est-ce sûr/ok/right?

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

La façon dont je fini par aller est d'utiliser QSharedPointer (Qt 4.5 et plus). Q_DECLARE_METATYPE (QSharedPointer ) – darkadept

Répondre

16

Il n'est pas prudent de rendre public le constructeur de copie d'un QObject. Vous pouvez cependant enregistrer un pointeur de classe en tant que métatype. i.e .:

Q_DECLARE_METATYPE (MyClass *);

C'est ainsi que Qt le gère avec QObject et QWidget.

5

Ce que vous demandez est parfaitement ok. Vous ne pouvez pas utiliser QObject s constructeur de copie (il est privé) dans la mise en œuvre de votre constructeur de copie, mais là encore, personne ne vous oblige à:

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

Selon les services que vous avez besoin de QObject, vous avez besoin pour copier certaines propriétés à partir de other, à la fois dans le copy ctor et dans l'opérateur d'affectation de copie. Par exemple, si vous utilisez QObject pour ses propriétés caractéristiques dynamiques, vous aurez besoin de copier ceux-ci, aussi:

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

De même, si vous voulez maintenir les connexions signal/sous.

+0

Bien, cela a du sens. Donc c'est possible mais il faut le coder très soigneusement. – darkadept

0

J'utilise une fonction distincte copyValue(const MyClass & other) pour copier les membres de données qui définissent les "valeurs" de l'instance MyClass. Cela garantit que je ne casse pas l'hypothèse de QObject identité unique, tout en étant capable de dupliquer les parties de la classe qui sont définies au moment de la compilation.

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

Et le cpp: QScriptValue QTFruitConstructor (QScriptContext */* contexte * /, QScriptEngine * interprète) { \t // renvoyer l'interpréteur-> toScriptValue (new QTFruit()); \t // ou \t return interpreter-> toScriptValue (QTFruit()); // mais vous avez besoin de la copie publique contructor } QTFruit :: QTFruit (const QTFruit et autres) : QObject() { } QTFruit :: ~ QTFruit() { } QTFruit: : QTFruit() { } vide QTFruit :: fromJScript (état eLedState) { \t int t = 0; } –

0

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

Bienvenue dans StackOverflow. Si vous voulez ajouter quelque chose à votre réponse précédente, vous pouvez l'éditer. Pendant que vous y êtes, vous pouvez également ajouter quelques explications à votre code. – void

Questions connexes