2009-05-12 2 views
12

私は何年もJavaで作業してきました。その間、私は広範な(あるいはたぶん頻繁に)反射を使用し、有用で楽しいと感じました。しかし、8ヶ月前に私は仕事を変えました。そしてJavaは単なる記憶であり、私はC++を手に入れています。だから私はC + +で反射メカニズムがあるかどうかは疑問だ。私はRTTIについて読んだことがありますが、それは決してJava(または他の言語)reflecionの力ではないと感じています。私はC++でこれを行う方法がないと思っています。私が間違っている?C++でのリフレクション

答えて

5

あなたがC++でコンパイル時に自分のタイプを知っていないとき、実行時にオブジェクトを操作するには、完全に一般的な方法を探しているなら、あなたは本質的に必要があります。

  1. インターフェース(抽象基底クラスを定義します。すべての純粋仮想メソッドとメンバーなし)がクラスがサポートしている可能性のある各機能について定義します。
  2. 各クラスは、(おそらく他のクラスの中から)実装したいすべてのインターフェイスから仮想的に継承する必要があります。今

pFooは、いくつかのオブジェクトx(あなたがxの具体的な種類を知っている必要はありません)へのタイプIFoo*のインターフェイスポインタを保持していると仮定します。あなたは、このオブジェクトが言ってインタフェースIBarをサポートしているかどうかを確認することができます

if (IBar* pBar = dynamic_cast<IBar*>(pFoo)) { 
    // Do stuff using pBar here 
    pBar->endWorldHunger(); 
} else { 
    // Object doesn't support the interface: degrade gracefully 
    pFoo->grinStupidly(); 
} 

このアプローチを使用すると、コンパイル時に関連するすべてのインタフェースを知っていると仮定し - あなたがない場合は、通常のCを使用することができなくなります++とにかくメソッドを呼び出すための構文。しかし、呼び出し元のプログラムが何を知らないのかを想像するのは難しいです。インターフェイスが必要です。インタラクティブなインタプリタを介してC++オブジェクトを公開したいと思う唯一のケースです。その場合でも、これを上記のパラダイムにshoehorningする(醜い保守集中的な)方法を考案できます。そのため、名前と引数を文字列として指定することでメソッドを呼び出すことができます。

他の側面は、オブジェクト作成です。具体的な型を知らなくてもこれを達成するには、ファクトリ関数と、クラスの固有の識別子を指定する必要があります。起動時にグローバルな工場に登録するようにクラスを調整することができます。as described here by C++ expert Herb Sutter - メンテナンスを大幅に緩和し、巨大なswitchステートメントのメンテナンスを回避します。単一のファクトリを使用することは可能ですが、これは、システム内のすべてのオブジェクトが実装しなければならない単一のインタフェースがあることを意味します(ファクトリはこのインタフェース型へのポインタまたは参照を返します)。一日の終わりに

、何をして巻くことは、基本的にはCOM(同型の) - dynamic_cast<IFoo*>QueryInterface(IID_IFoo)と同じ仕事をして、すべてのオブジェクトによって実装される基本インタフェースは、IUnknownに相当します。

1

RTTIは解決策です(Javaのどの部分をRTTIに入れないと思いますか?)そうでなければ独自のオブジェクトフレームワークを実装できます - 独自のC++オブジェクトはすべてリフレクションインターフェイスを継承し、

+1

私はRTTIについての知識は乏しいと思いますが、RTTIを使用してオブジェクトのメソッドや属性のリストを取得する方法はありますか? – aitor

+2

@aitor:いいえ、私はそう信じていません。 RTTIは実行時にオブジェクトのタイプを教えてくれますが、この情報をメソッドや属性の可用性などのより正確なものに変換することは、あなたの責任です。 –

+1

複雑なRTTIは次のようになります。http://www.codeproject.com/KB/library/vcf_rtti.aspx – Francis

15

C++標準では、「メタデータ」などの概念をカバーしていないので、何のポータブルは、すでに述べたRTTI以外の実行時リフレクションの方法は、(そのことについては、別のコンパイラやプラットフォーム間)ありません。

C++では、コンパイル時の反映も考えられます(boost::type_traitsboost::type_of)が、NemerleやLISPに比べて制限があります。

メジャーなフレームワーク(MFC、Qtなど)は、実行時にメタ情報を抽出することができますが、すべての種類の特殊なアノテーションが必要です(例としてRUNTIME_CLASSなどを参照)。

0

依存性注入(いくつかのインタフェース^ H^H^H^H^^純粋な抽象クラスの実装)を使用している場合は、それを含む.dllまたは.soファイルの動的ロードを試みるかもしれませんプラグインが何であれ、その実装は今日のものです。

はおそらく、これは同時に、物事の複数の実装ではうまく機能しませんように、ストローで把握します。

3

あなたはVisitorパターンを使用する必要があります。反映できるクラスは、訪問者クラスを受け入れるReflectメンバ関数を与えた基底クラスを継承する必要があります。次に、Reflect関数は、他のメンバーに関する情報または機能を訪問者に渡します。

多くの人気のあるライブラリは、たとえば、MFCでSerialize機能がこれを行うが、特に直列化のために、特定のケースのために、このパターンを使用します。

ビジターがメンバー関数への動的呼び出しを行い、データメンバーの値を取得または設定できるようにシステムを設計することはおそらく可能です。しかし、それを維持する各クラスの責任がありますReflect手作業で書かれた関数。クラスの構造の繰り返しです。

1

リフレクションは、コンピュータプログラムは、独自の構造と動作を確認し、修正することが可能なプロセスです。私はあなたがC++でのリフレクションをどのように行うことができるか分かりません。 RTTIは、実行時にメモリ内のオブジェクトのデータ型に対してのみ有効です。

4

my answer to a similar questionを見てください。提案される両方のソリューション(XRTTIとOpenC++)は、ビルドプロセス中にリフレクションメタデータを生成する外部ツールに基づいています。

0

C++で何をする必要がありますか、どのプラットフォームで作業していますか?私は完全なクラス定義を取得し、このデータを使用して関数を呼び出す方法の1つを知っていますが、Windowsでは動作しますが、他のプラットフォームについてはわかりません。アイデアは、DLLまたはexeエクスポートテーブルからデータを取得することです。まともな実装を得るまでに数か月かかっていましたが、リフレクションをサポートする言語ではすべてのことが行われます。

+0

答えはどういう意味ですか?あなたが話すまともな実装はどこですか? –

関連する問題