2011-07-23 10 views
6

the QObject documentationと多くの人が説明するように、QObjectは同一性を持ち、コピーコンストラクタと代入演算子を隠します。C++ Qt反映とコピーと割り当て

しかし、私はQObjectからそのダイナミックプロパティー機能または信号/スロット機能を派生していません。私はの反映、またはFoo::staticMetaObjectにアクセスする必要があります。

class Foo : public QObject { 
    Q_OBJECT 
    Q_ENUMS(Color) 
public: 
    enum Color { Blue, Red, Pink }; 
private: 
    Color color; 
}; 

Q_DECLARE_METATYPE(Foo::Color) 

私はその後でFooをコピーすることはできません。

Foo a; 
Foo b; 
a = b; 

この場合にはコピーと割り当てを許可するための最良の方法は何ですか?私は絶対にコピーコンストラクタと代入演算子を書く必要がありますか?彼らはどのように見えるでしょうか?反射はまだ機能しますか?

+0

あなたは 'QObject'を使用しないことを意味します。リフレクションはこの問題の原因ではないからです。問題は、QObjectがコピーと割り当てをプライベートにすることです(理由があります)。 –

+1

@kristianp、良い提案、私はその編集* if * @alexisdmは私の正確な質問に正確な答えを提供していないだろう。多くの場合、答えは「あなたがしたいことをしないでください」ですが、この場合合理的な答えであっても、私がやりたいことをさせるものもあります: 'Q_GADGET' –

答えて

14

あなたは

  • クラス名の反射を持つことにのみ関心がある場合は、
  • 列挙型とフラグ(Q_ENUMS、Q_FLAGS)、
  • クラス情報(Q_CLASSINFO)、

あなたはQ_GADGET instead of Q_OBJECTを使用できます:

class Foo { 
    Q_GADGET 
    Q_ENUMS(Color) 
public: 
    enum Color { Blue, Red, Pink }; 
private: 
    Color color; 
}; 

これはFoo::staticMetaObjectを宣言して定義します。

+0

うわー、私前に 'Q_GADGET'から聞いていませんでした。したがって、軽量で静的な 'Q_OBJECT'のバージョンのように見えますが、これは(このような)いくつかのケースで非常に便利です。悲しいことに、少なくとも私はそれを見つけることができませんでした。これは非公式であり、将来的には動作することが保証されていません:( – leemes

+0

@leemesこれは、QObjectページの 'Q_OBJECT'のところで簡単に述べられています(上記のリンクを追加しました)私は、他のもののためにmocのソースコードを検索するときにしか見つけられませんでした。 – alexisdm

1

私はqtについてよく分かりませんが、コピーコンストラクタが許可されていない場合は、理由があります(投稿したリンクで説明します)。デザインを変更することはできません。

まだあなたが主張するなら、memcpyはあなたの最後の手段になります。私は個人的にはお勧めしません。なぜなら、あなたは深刻なコピー、vtableなど、常に些細なことではないことに気を配らなければならないからです。

2

派生クラスにコピーコンストラクタとコピー代入演算子の両方を実装することはできますが、デザインが悪い可能性があります。この例を取る:

#include <iostream> 

class Base { 
public: 
    Base() {} 

private: 
    Base(const Base& other) { 
     std::cout << "Base copy constructor invoked!" << std::endl; 
    } 
}; 

class Derived : public Base { 
public: 
    Derived() {} 

    Derived(const Derived& other) { 
     std::cout << "Derived copy constructor invoked!" << std::endl; 
    } 
}; 

int main(int argc, char** argv) { 
    Derived a; 
    Derived b = a; 

    return 0; 
} 

これはうまくコンパイルされます。しかし、期待どおり、結果のプログラムを実行すると、すべてが表示されますDerived copy constructor invoked!です。基本クラスがコピーコンストラクタ/コピー代入演算子をプライベートとして宣言しても、派生クラスが独自のバージョンを実装することはできません。 は、派生クラスが基本クラスバージョンを呼び出すのを防ぎます。

そしてそこには問題があります。オブジェクトのすべての部分を確実にコピーして、本当に2つの別個のコピーを持つようにするのは常に良い方法です。オブジェクトの一部には基本クラスが所有するデータが含まれているため、完全なコピーが確実に行われるように、基本クラスのコピーコンストラクタ/コピー代入演算子を必ず呼び出してください。しかし、そのデータは設計上、コピーできません。したがって、オブジェクトのすべての部分をコピーすることは不可能です。

このデザインにこだわりたいのはあなた次第です。あなた自身に尋ねるべき重要なことは、あなたの派生クラスは本当にコピー可能である必要があるということですか?そうでなければ、心配することはありません!

関連する問題