関数へのポインタ
関数へのポインタは、C, C++, Dやその他Cを基にしたプログラミング言語におけるポインタの一種である。関数へのポインタを参照外し(デレファレンス)して実引数を与えると、そのポインタが指し示す関数を呼び出せる。Cなどのプログラミング言語では、switch文を置き換えてコードを単純にするために使われることがある。
関数オブジェクトも関数へのポインタと同じような使い方が可能だが、関数オブジェクトは関数呼出演算子を実装したクラスなどのオブジェクトであるという点が異なっている。そのため、関数オブジェクトはデータを保持でき、クロージャを再現することもできる。ゆえに、関数オブジェクトは、単純な関数へのポインタよりも強力である。
多くの「純粋な」オブジェクト指向プログラミング言語(Javaなど)では、関数へのポインタを使用できないが、そのような言語では、メソッドを1つだけ持つインタフェースを使用することで同様のことを行える。また、C#やVisual Basic .NETなどといった.NET Framework用の言語では、関数へのポインタを型安全にしたものとして、デリゲートが使用可能である。
第一級オブジェクトとして関数を使用できる言語では、関数も引数で渡したり、戻り値で返したり、他の関数から動的に作成したりできるなどデータ同様に扱えるため、関数へのポインタは必要とされない。
目次 |
Cでの例 [編集]
この例では、関数へのポインタとしてnew_functionが宣言され、そこへ関数my_functionのアドレスを割り当てている。そしてnew_functionを通じて関数を呼び出している。
#include <stdio.h> static int my_function(int a) { printf("my_function: %d\n", a); return 2 * a + 3; } int main(void) { int (*new_function)(int a) = my_function; int x; x = (*new_function)(10); printf("main: %d\n", x); return 0; }
註:(*fp)(arg)という構文は、関数へのポインタfpを通じて関数を呼び出す構文である。しかしCではfp(arg)という構文も認められている[1]
次の例では、関数へのポインタを引数として他の関数に渡している。ここでは、関数functionが、先の例のように関数へのポインタを通じて呼び出される。関数callerは、引数として関数へのポインタと整数値を1つ取る。引数の整数値は、その関数へのポインタを通じて関数を呼び出すときに渡す引数として用いられる。そこで宣言されている関数へのポインタのプロトタイプに適合しさえすれば、callerの第一引数には、どんな関数でも渡すことが可能である。
#include <stdio.h> static void function(int a) { printf("my_function: %d\n", a); } static void caller(void (*new_function)(int a), int p) { (*new_function)(p); } int main(void) { caller(function, 10); return 0; }
3番目の例でも関数へのポインタを引数として他の関数に渡して用いている。関数fは、指定された区間で積分
の近似を計算する関数integへ渡されている。xの値を求めるためにf(x)がintegから呼び出されている。integでは、double型の引数を1つ取り、double型の値を返しさえすれば、どんな関数でも計算させることが可能である。
double integ(double a, double b, double (*f)(double x)) { double sum = 0.0; double x; int n; // 積分{a,b} f(x) dxの計算 for (n = 0; n <= 100; n++) { x = (n/100.0)*(b-a) + a; sum += (*f)(x) * (b-a)/101.0; } return sum; }
関数へのポインタを定義する際には、typedefを用いるのが便利である。
#include <stdio.h> #include <math.h> typedef double (*Fx)(double x); int main(void) { Fx f[3]; f[0] = cos; f[1] = sin; f[2] = tan; printf("From 0 to pi/4:\n"); printf("\t integ of cos = %g\n", integ(0, M_PI/4, f[0])); printf("\t integ of sin = %g\n", integ(0, M_PI/4, f[1])); printf("\t integ of tan = %g\n", integ(0, M_PI/4, f[2])); return 0; }
脚注 [編集]
- ^ Summit, Steve; 北野 欽一 (1996年2月26日). “C FAQ 4”. 4.12: 関数を呼ぶのに、ポインターを通す方法をみたことがある。どうなってるの。. 2008年10月14日閲覧。。
関連項目 [編集]
外部リンク [編集]
- Pointer Tutorials, C++ documentation and tutorials
- Function Pointer Tutorials, a Guide to C/C++ function pointers