• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:【C++】関数ポインタの使い方)

C++関数ポインタの使い方

このQ&Aのポイント
  • C++関数ポインタの使い方で悩んでいませんか?
  • グローバルメソッドとして定義したメソッドを関数ポインタに代入することはできますが、クラスのメンバメソッドは代入できません。
  • 関数ポインタに外部参照でメソッドを代入することはできないのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

(1) インスタンスメンバ関数は代入できない 既に回答がありますが、インスタンスメンバ関数のポインタは int (MPointerList::*)(int,int) という型であり、静的な関数のポインタ int (*)(int,int) とは異なる型です。そもそも、インスタンスメンバ関数を呼び出す時は引数 a, b だけでなく持ち主のオブジェクトインスタンス mP も必要なのです。その時の呼び出し方が、(mP.*memberFunctionPointer)(a,b) になる訳です。 (2) 静的メンバ関数は代入できる 因みに、インスタンスメンバ関数ではなく、静的メンバ関数のポインタは通常の関数ポインタと同じ型です。 呼出にオブジェクトインスタンスを必要としないためです。 -------------------- class MPointerList{ public: static int f(int a, int b){ return a * b; } }; FUNC_POINTER fp = &MPointerList::f; // OK -------------------- (3) オブジェクトインスタンスと一緒に取り扱う 「メソッド」と書いている辺り、C# のデリゲートや Delphi のメソッドポインタの様な使い方を期待していますか? (C++ ではメンバ関数の事をメソッドとは言わないので…。) 実は、デリゲートやメソッドポインタは、内部的には単なる関数ポインタではなく (オブジェクトインスタンスへの参照) と (メンバ関数へのポインタ) のペアです。C++ でも同様の事をしたければ、同じようにインスタンスへの参照とメンバ関数へのポインタのペアを取り扱う関数オブジェクトのクラスを用意すれば良いのです。 そして、C++11 でその様なクラスが標準ライブラリに追加されました。std::function です。Visual Studio 2010 以降など C++11 に (部分的に) 対応している最近のコンパイラで使えます (もちろん、古いコンパイラではコンパイルできないコードになってしまうという問題はありますが)。更に、C++11 のラムダ式と組み合わせればその様な関数オブジェクトの生成も簡単になります。 -------------------- #include <functional> using namespace std; int globalFunction(int a, int b){ return a * b; } class MPointerList{ public: static int staticMemberFunction(int a, int b){ return a * b; } int instanceMemberFunction(int a, int b){ return a * b; } }; int _tmain(int argc, _TCHAR* argv[]) { std::function<int(int,int)> fp; // もちろん、静的な関数は代入できる fp = globalFunction; // 静的なメンバ関数も代入できる fp = &MPointerList::staticMemberFunction; MPointerList mP; // &MPointerList::f と mP への参照から関数オブジェクトを生成し、fp に代入できる fp = std::bind(std::mem_fn(&MPointerList::instanceMemberFunction), std::ref(mP), std::placeholders::_1, std::placeholders::_2); // ラムダ式を使えば、上と同等の事をより簡単に書ける。 fp = [&mP](int _1,int _2) -> int{return mP.instanceMemberFunction(_1,_2);}; cout << fp(1,2) <<endl; getchar(); return 0; } -------------------- ★注意★ mP の寿命に注意して下さい。変数 mP の寿命が尽きた後も、fp の中に mP への参照が残りますが、この時に fp を呼び出すと異常動作します。変数 mP のスコープの外で fp を使いたい場合には、MPointerList を動的に確保して寿命を管理する必要があります。その為には、C++11 の std::shared_ptr (~寿命自動管理機能付きポインタ) を使うと楽です。 -------------------- #include <memory> 中略 std::shared_ptr<MPointerList> mP2=std::make_shared<MPointerList>(); fp = [mP2](int _1,int _2)->int{return mP2->instanceMemberFunction(_1,_2);}; //※参照キャプチャ [&mP2] ではなく値キャプチャ [mP2] --------------------

haraheri31
質問者

お礼

akinomyogaさん とても詳しいご説明 大変有難うございました。 C++は本当に様々なことができるのですね。 自分も精進しようと思います。

その他の回答 (1)

回答No.1

> 関数ポインタに外部参照でメソッドを代入することは出来ないのでしょうか? できません。 やるならこんな↓カンジ。 #include <iostream> using namespace std; class MPointerList{ public: int f(int a, int b){ return a * b; } }; int main() { typedef int (MPointerList::* FUNC_POINTER)(int, int); FUNC_POINTER fp; fp = &MPointerList::f; MPointerList mP; cout << (mP.*fp)(1,2) <<endl; getchar(); return 0; }

関連するQ&A

専門家に質問してみよう