• 締切済み

VC++/MFCでリフレクション

Javaでは、ObjectのgetClass()でClassクラスの インスタンスが取れ、実行時に指定した、メソッド名や、引数で、動的にメソッドを呼びだすようなリフレクション機能が使用できます。 同様のことをC#でも実装したことがあります。 VC++/MFCにて、このようなリフレクションをやるやり方を教えてください。 C++の標準あるいわ、MFCの機能など、どちらでもよいです。 メタクラス型のようなものを実行時に取得して、リフレクションする方法だと思います。 質問の内容はVC++.NETやVC++/CLIではないです。そちらのほうでのやり方は既に発見しました。

みんなの回答

回答No.7

#1で発言しました。 私もいろいろ勉強になりました。 軽い気持ちで vtable とか書いちゃったから。 でも違和感、あります。 無いのがわかっていながら何故そこまでこだわるのか。 しかも必要だ、という根拠が -- 特に、JUnitやNUnitなどのテストの自動化ツールがサポートされてるわけでもないですし、あったとしても使われてなくて、テストコードが残ってなければ、別の部分に影響を与えていないかの確認は担当者の裁量になってしまいます。 ---- の部分。 これはリフレクションが必要というより  影響が無い、と証明できるテストコードが無いと担当者を信頼できない  リフレクションを使えば変えた部分が容易に把握できる ですよね。 これは仕事の進め方でどうにでもなる部分だと思います。 元々はあったらいいな的な質問と思いますが、それがないと改修ができません、みたいなレベルまで昇華している気がいます。 そんなに必要ですか、と思っちゃいます。 --------- >要するに、パスタを茹でるための調理器具が必要ということですね。 この「例え??」私にはよくわからないです。 あまり、頭がよくないので・・。 パスタと、調理器具がなんでしょうか? ------- パスタは鍋でも作れるけど、パスタ専用の調理器具で作れないと気持ち悪いと感じる人 内容は推して図るべしですね

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.6

#2です。ちょっと捕捉。 「プログラマが個別の機能とその負荷をトレードオフする。  その機能を使わなければ、実行速度やメモリサイズの負荷を受けない」 C++ の設計思想では、静的評価(コンパイラが苦労する)が重視されます。 type_info 程度の負荷でも抵抗があったわけで、めったに使わないリフレクションでは到底… # RTTI の苦労話とかは先の書籍など参照。 > ↑クラス名からオブジェクトをつくったり、 > 継承関係を調べることぐらいしかできないようです。 最初からそう申し上げています。 そして、通常の開発でそれ以上の機能が必要になることは稀です。 (ないとは言いませんが、頻繁に必要になるのであれば、設計から見直すべき状態です) > No.1さんの言ってるvtableで実現できるなら。 これだけでは、できません。 もちろんコンパイラ依存ですが、大抵の場合実行時にvtableを解析したとしても、一部の関数のそれも先頭アドレスくらいしか情報はありません。 ・関数等の名称は不要なため、実行時に情報は残っていません。 ・virtual でない関数はコンパイル時に静的解決されるため、 vtable にはアドレスも載りません。 ・関数の型情報等もコンパイル時に静的解決するため、実行時に情報は残っていません。 そもそも実行ファイルに名称などの情報が保持されないため、 自分で全て付加/保存/参照などの機能を用意しない限り、 リフレクションを実現することはできません。 おそらく、template やプリプロセッサ等を駆使したコードを書いて情報を保存した上で、実行時の処理を作成することになるかと思います。 汎用的な対応難しいと思いますし、プリプロセッサを自作した方が早い/綺麗かも。 # 環境依存でよいなら、いっそデバッグ情報でも添付して、それを解析した方が早いかも…(技術的興味以外ではお勧めしませんが

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.5

#3です。 #4の回答と重なる部分もあると思いますが... > そんなに深刻になる必要もないと思います。 > (中略) > とすれば良いことだと思います。バグが無い限りcatchされることもないと思います。 動かしてみるまでバグが分からないこと自体が問題なのです。 > ただ、他の言語でできたことができないと、気持ち悪いものです。 その論法でいけば、多重継承も、まともなテンプレートも、フリー関数も、大域オブジェクトも、プリプロセスも、生のポインタもない言語は気持ち悪くて仕方ありませんよね。 > ・どんなクラスのオブジェクトにでも適用したい時。 > ・予想できなかった変更で、部分的に汎用的なパッチの当て方 > > などの時にうまく逃げる術がないと、不安なんです。 要するに、パスタを茹でるための調理器具が必要ということですね。

bean_atkinson
質問者

お礼

回答ありがとうございます。 >動かしてみるまでバグが分からないこと自体が問題なのです。 そうですね。問題ですね。 ただ、状況によっては、リフレクションを採用しない方法での改修のほうがよっぽど、危険度が高いケースもあると思います。 特に、JUnitやNUnitなどのテストの自動化ツールがサポートされてるわけでもないですし、あったとしても使われてなくて、テストコードが残ってなければ、別の部分に影響を与えていないかの確認は担当者の裁量になってしまいます。 部分的でもいいから小さく汎用的にまとめて逃げたほうが安全なときもあります。 いつも、いつも、不必要にリフレクションを使うのはよくないですが、リフレクションの選択肢が無いのもあまり、良く無いなぁって感じました。 >その論法でいけば、多重継承も、まともなテンプレートも、フリー関数も、大域オブジェクトも、プリプロセスも、生のポインタもない言語は気持ち悪くて仕方ありませんよね。 そうですね。それを使いたい人には、気持ち悪いんでしょうね。気持ち悪い言語でも仕事上使わざるを得ないことはありますし。 気持ち悪いから、本当に無いのか、単に自分が知らないだけなのか確認したくなるでしょうね。 >要するに、パスタを茹でるための調理器具が必要ということですね。 この「例え??」私にはよくわからないです。 あまり、頭がよくないので・・。 パスタと、調理器具がなんでしょうか?

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.4

#2です。 C++ の設計思想の問題ですが、リフレクションはありません。 おそらく FAQ です。 静的型保証の他にも、メモリ配置など低いレイヤでデメリットがあるため、C++ の設計時にそのような機能を付加していません。(組み込み環境など、邪魔になる環境もありえます) > 他の言語でできたことができないと、気持ち悪いものです。 それは単に、個人の感情的な問題です。 全てで同じことができるなら、別の言語は要らないと思いませんか。そういうことです。 C++ には C++ の特性(利点も欠点も)があります。 「リフレクションで逃げる」という発想が、C++ の設計思想上汚いと考えられ、そのためのデメリットを採らなかったと。 # 汚いパッチには、void* やキャストを使ってください。 設計思想を理解するには、設計者の著書がいいと思います。

参考URL:
http://www.amazon.co.jp/exec/obidos/ASIN/4797328541/503-9001616-3417506,http://www.amazon.co.jp/exec/obidos/ASIN/4756118
bean_atkinson
質問者

お礼

回答ありがとうございます。 >C++ の設計思想の問題ですが、リフレクションはありません。 おそらく FAQ です。 やはりないみたいですね。 C++自体になくても、VC++/MFCの環境であればよいとおもったのですが・・。 >。(組み込み環境など、邪魔になる環境もありえます) MFCである以上、PC上のソフトなどで、そんなこと考慮せず、単にあれば便利だとおもったのですが。 ないのなら仕方ないです。 >それは単に、個人の感情的な問題です。 >全てで同じことができるなら、別の言語は要らないと>思いませんか。そういうことです。 >C++ には C++ の特性(利点も欠点も)があります。 好きで、個人的にやってるというよりは仕事でMFCを使用しなければならなさそうなので・・。 C++の設計思想よりも、単にリフレクションがあればいいなぁって、程度にしか考えていないです。 ># 汚いパッチには、void* やキャストを使ってください。 void*、キャストと、リフレクションにはなんの関係もないです。 void* やキャストを使うとその汚い部分で、ifを使うことになります。それすらしたくないからリフレクションがあればいいなぁっとおもったんですが。 ないなら、仕方ないです。 ただ、C++の設計思想がわかれば、もっと違った発想もでるかもしれないです。 本位・不本意問わず、せっかくやるなら、設計思想がわかって、考え方広がったほうが、自分としても得かもしれない。そういう意味で、どうもありがとうございました。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

他の方も回答されているように、C++にはリフレクションはありません。動的にメソッドを呼び出す方法は、静的な型安全性を放棄するようなもので、C++の設計思想と相容れないような気もします。 具体的にどんなことをしたいのかが分かれば、適当な代案を紹介できるかもしれません。 予想ですが、おそらくテンプレートを使えばやりたいことは実現可能な気がします。 本当の意味で動的にメンバ関数を選択したいのではなくて、単にどんなクラスのオブジェクトにでも適用したいだけなんですよね。違っていたらすみません。

bean_atkinson
質問者

補足

>静的な型安全性を放棄するようなもので、C++の設計思想と相容れないような気もします。 そんなに深刻になる必要もないと思います。 try { リフレクション; }catch(型、メンバが発見できない) { //エラー処理、 //メッセージ出力、OR //ログ出力等 } とすれば良いことだと思います。バグが無い限りcatchされることもないと思います。 >具体的にどんなことをしたいのかが分かれば、適当な代案を紹介できるかもしれません。 具体的にしたいことはないです。 MFCで仕事する必要があって、学習しているだけです。すいません。 ただ、他の言語でできたことができないと、気持ち悪いものです。 以前、フレームワークに近いようなものを作った時に、リフレクションを使いましたし、 急に、予想もしなかったところで、追加の要求がでた時に、リフレクションを使ってうまくやり過ごしたこともあります。 クラスの継承関係もバラバラでしたが、たまたま、同じ形をしたXMLデータを(別のデータですが・・)つかってて その部分を扱うメンバの名称が似ていて、法則性があったので、リフレクションを使いました。 名前の付け方に依存したコードを書くのも、あまり良いないし、いろいろ考えましたが、 そうしない場合の修正量と、危険度、影響範囲度を考慮した結果、それが最善だと考えてそうしました。 >予想ですが、おそらくテンプレートを使えばやりたいことは実現可能な気がします。 本当の意味で動的にメンバ関数を選択したいのではなくて、単にどんなクラスのオブジェクトにでも適用したいだけなんですよね。違っていたらすみません はじめから、自分が予想している範囲内での汎用性を求めるならテンプレートでよいと思います。 それにいろんな人がコードをいじってますので、統一感のあるコードを見ることも、経験上あまりないんです。 そんなときになにかの共通性を見つけてリフレクションをつかって、うまく逃げれるときが結構あるんです。 もともと、テンプレートで無かった部分をテンプレートに変更すると、その型を利用している側で、修正が発生します。 テンプレートを利用する側でどの型で実際に具体化するかの判断のためにif文が必要になるケースもでるかもしれません。 ・どんなクラスのオブジェクトにでも適用したい時。 ・予想できなかった変更で、部分的に汎用的なパッチの当て方 などの時にうまく逃げる術がないと、不安なんです。

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.2

> C++の標準あるいわ、MFCの機能など、どちらでもよいです。 C++ 標準に、リフレクション機能は存在しません。 実行時に取得できる情報は type_info 程度です。 これが Class のインスタンスというところですが、 ここにメソッドなどの情報を取得する手段はありません。 MFC の機能でもずばりはなかったと思います。 # メッセージのリフレクションは別物ですし...。 但し、対象がDynamic な CObject の派生クラスであれば、 GetClass 相当には CRuntimeClass が使えます。 > VC++/MFCにて、このようなリフレクションをやる > やり方を教えてください。 CRuntimeClass で事が足りるなら、CObject の利用が考えられます。 事足りない場合、最善手は、リフレクション以外の方法を考えることです。 次善は、リフレクション処理を自作(または調達)することです。

bean_atkinson
質問者

お礼

http://msdn2.microsoft.com/ja-jp/library/fych0hw6(VS.80).aspx ↑クラス名からオブジェクトをつくったり、 継承関係を調べることぐらいしかできないようです。 No.1の人も自作する方向性を示していましたが。 私にはそこまでの能力はないです。 リフレクション以外の方法でできることは多いですが。 リフレクションでやるとスマートでスッキリすることも多いです。 ありそうな気がするんですが。逆にない理由も思いつかない。 No.1さんの言ってるvtableで実現できるなら。 私のような人間が考える前にだれかがつくっていそうですし・・・ あるとおもったのですが・・。

回答No.1

プログラムは書きませんが、vtable を自分で解析すれば同じような仕組みが出来るかもしれません。