2009-06-05 142 views
9

我有一個類是QObject的子類,我想註冊爲元類型。 QObject documentation指出複製構造函數應該是私有的,但QMetaType documentation指出一個類型應該有公共默認構造函數,公共複製構造函數和公共析構函數。QObject的子類,qRegisterMetaType和私有拷貝構造函數

我可以重寫QObject的私有拷貝構造函數並聲明一個公共拷貝構造函數,但是這是安全的還是正確的?

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

我最終去的方式是使用QSharedPointer(QT 4.5及以上)。 Q_DECLARE_METATYPE(QSharedPointer ) – darkadept 2009-06-05 17:02:58

回答

16

公開QObject的拷貝構造函數是不安全的。不過,您可以將類指針註冊爲元類型。即:

Q_DECLARE_METATYPE(MyClass *);

這就是Qt如何用QObject和QWidget處理它。

5

你要求的是完全正確的。不能使用QObject的拷貝構造函數(它是私有的)在你的拷貝構造函數的實現,但還是那句話,沒有人強迫你:

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

取決於什麼服務從QObject需要,你需要在副本分配器和複製分配操作員中從other複製一些屬性。例如,如果你使用的QObject爲它的動態屬性功能,你需要複製這些,太:

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

同樣的,如果你想保持信號/槽連接。

+0

對,這是有道理的。所以這是可能的,但需要非常仔細地編碼。 – darkadept 2009-08-10 16:12:08

0

我使用單獨的copyValue(const MyClass & other)函數來複制定義MyClass實例的「值」的數據成員。這確保我不會破壞假設QObject的唯一標識,同時仍然能夠複製在編譯時定義的類的各個部分。

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

和cpp:QScriptValue QTFruitConstructor(QScriptContext */* context * /, QScriptEngine * interpreter) { \t // return interpreter-> toScriptValue(new QTFruit()); \t //或 \t return interpreter-> toScriptValue(QTFruit()); //但你需要的公共副本構造器 } QTFruit :: QTFruit(常量QTFruit及其他) :QObject的(){ } QTFruit ::〜QTFruit(){ } QTFruit: :QTFruit() { } 空隙QTFruit :: fromJScript(eLedState狀態) { \t INT噸= 0; } – 2014-12-16 14:40:50

0

和自備電廠:

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

歡迎來到StackOverflow。如果你想添加一些東西到你以前的答案,你可以編輯它。當你在它的時候,你可能也想爲你的代碼添加一些解釋。 – void 2014-12-16 15:11:56