2012-02-28 24 views
3

私はここで挑戦の種を持っています。私は将来のプロジェクトのためのエクササイズとユーティリティキットの両方としてリフレクションライブラリに取り組んでいます。それを機能させるためには、私はすでにそれが不可欠であることを容認しました。貴重な反射データを得るためには、クラスのボディに少なくともわずかなコードを追加する必要があります。リフレクションを実装する:クラスの親を見つける方法

しかし、私は可能な限りミニマルスティックになりたいと思います。そこで、いくつかの既存の実装を勉強した後、私に合ったコンセプトを見つけました。単純化するために、パターンは次のようになります。

class Base 
{ 
    int baseFoo; 
    double baseBar[5]; 
    RTTINFO(baseFoo, baseBar); 
}; 

(...) 

Base sth; 
std::cout << TypeInfo(sth).variables[0].name; << std::endl; 
// I don't mind if the way of accessing the type info changes totally 

いくつかの一般的なプログラミングを使用して、私はこのRTTINFOマクロと建物種別情報構造の後ろに好きなものを隠してほとんど達成することができます。私はタイプ、名前、配列のサイズなどを取得することができます。しかし、私はこのように、さらに一歩を行くと継承を紹介したいとき:

その後、
class Derived : public Base 
{ 
    std::string foo; 
    char* bar; 
    /* RTTIPARENT(Base); <-- I want to avoid this */ 
    RTTINFO(foo, bar); 
}; 

私はベースをspecifing避け、まだ入ることができるようにしたいと思いますメンバーのRTTI。 BaseRTTINFO(...)Derivedにいくつかのヒントを密輸して可能にする方法があることを願っていました。だからそこにはありますか?

主な要件は次のとおりです。

  1. 私は、基本クラスのどこにでもなく、言語定義の場所を指定する必要はありません。そして、私はどのマクロでもclass Derived : public Baseをラップしたくありません。
  2. RTTIINFOは、影響を受けるクラスに必要な言語とメモリバイアスを追加できます。
  3. RTTINFOマクロに、必要ならば何トンものコードを入れることができます。
  4. BaseとDerivedの両方が、まったく同じRTTINFOマクロを使用します。これは、もちろん、さらにインフェリメンテーションで再利用される可能性があります。多重継承の問題を除外しましょう、単一の継承は十分に複雑に見えます。
  5. DerivedBaseのRTTIにアクセスする必要はありませんが、RTTIデータを処理する他の外部ヘルパークラス/関数でもかまいません。ただし、プライベートメンバー変数をサポートする必要があります。
  6. 私はコンパイルと実行時のコストを気にしません - 継承ツリーを構築する、既存のすべてのクラスをポーリングするなどの計算が実行時に実行される必要がある場合は、常にプログラムの初期化段階に移動できる方法があります。私にとっては大したことではありません。
  7. 可能であれば、言語サポートRTTIは、一部のプロジェクトでは無効にする必要があります。とにかく、私はそれでも解決策を見つけられませんでした。
  8. 追加のコンパイルステップを追加することはできません。

ワンノート:たぶん私は​​を使用することができますが、それは一般的なコンパイラのために働くだろうしても、C++標準では、私がここに継承関係に頼ることはできないと言います。

ありがとうございました!

アンドリュー

+1

マクロで現在のクラス名を取得するにはどうすればよいですか? –

+5

Reflectionはチェーンソーが歯科医の練習に属するほどあなたのC++の "ユーティリティキット"に属します。 –

+0

正確には、あらゆる種類のリフレクション/タイプ情報が必要な場合は、非常に多くのマクロで終わることになり、有用ではありません。ちょうどGObjectを見てください。 – farnoy

答えて

3

(でもC++ 11が本当の反射を持っていないので)あなたは現在のC++ 03やC++ 11コンパイラで全反射を持っていません。

あなたは、いくつかのメタクラスコードを生成することがありました(良い例としてQt MOCを見て)

あなたはあなたのC++コンパイラを拡張することができます。 GCCの場合は、プラグインを作成するか、MELTという拡張子を付けることを検討してください。

+0

これが私に8)を加えた理由です。私には、新しいコンパイルステップを追加することは、リフレクションを動作させるためのあらゆる試みをあきらめてしまうほど多くの欠点があります。 – Andrew

+0

その後、QtのようにC++のメタクラスコードを生成する必要があります。あなたはおそらく 'QObject'(GUIなしでQCore)を使用していると考えましたか? –

+0

提案してくれてありがとう、本当にQObjectはやっていますが、それを達成するにはまだ 'moc'が必要です。私は十分にはっきりしていませんでした。「追加のコンパイルステップ」では、コード生成と前処理も意味します。しかし、デバッグ設定でのみQt拡張機能を使用し、プロジェクト(SCMを含む)を同時に保守することは可能かもしれないと思いますか?それは価値がありませんか? – Andrew

2

DSL(ドメイン固有言語)の種類を設定し、そのDSLのクラス記述に基づいてリフレクションを行う小さなコード生成フレームワークを設定することで、コード生成を使用することを検討できます。これはおそらくデータ・コンテナと継承部分でのみ動作し、動作部分(メソッド)では動作しませんが、大部分のJava advocatsが貧血オブジェクト・モデルを好むので、これはその傾向に完全に当てはまります。

C++には真の多重継承があるため、その欠点を克服して、生成されたクラスから行動クラスを派生させることができます。

Stefan

関連する問題