プログラミングにおけるポインタの一種で、関数を指し示すものです。
多くの場合、実体としては「どの関数を呼び出すか」を表す値(メモリアドレスなど)を保持することによって、ある1つの関数を指し示します。指し示している関数がないことを示すためにヌルポインタを用いることができます。また、関数には仮引数や戻り値があるため、関数ポインタもそれらの型を含むことが一般的です。
関数ポインタを間接参照することにより、指し示す先にある関数を呼び出すことができます。
保持している値を変更することによって、呼び出す関数をあとから差し替えることができます。これにより、条件に応じて処理を切り替えたり、共通処理に利用者側の処理を渡したりする(コールバック)ことを実現しやすくなります。
関数を指し示している関数ポインタに対して、オブジェクトを指し示しているポインタをオブジェクトポインタと呼ぶことがあります。
C言語の関数ポインタは、関数の仮引数や戻り値の型を含むように宣言します。
int f(const char* str); // 関数の宣言
int (*fp1)(const char*) = f; // 関数ポインタの宣言と初期化
int (*fp2)(const char*) = &f; // 同上関数ポインタを間接参照することにより、指し示す先にある関数を呼び出せます。オブジェクトポインタと同様、* を用いて間接参照しますが、関数ポインタの場合はより簡単に、通常の関数であるかのように呼び出すこともできます。
int ret1 = (*fp1)("hello"); // 関数ポインタを間接参照して関数を呼び出す
int ret2 = fp2("hello"); // より簡単な呼び出し方C言語の関数ポインタに関する詳細な解説は、C言語編「ポインタ⑧(関数ポインタ)」のページにあります。
C++ の関数ポインタはC言語のものと同様です。名前空間内にあるフリー関数や、静的メンバ関数を関数ポインタで指し示すことも可能です。
namespace N {
int f(const char* str); // 関数の宣言
}
struct S {
static int f(const char* str); // 静的メンバ関数の宣言
};
int (*fp1)(const char*) = N::f;
int (*fp2)(const char*) = S::f;例外的なのは静的でないメンバ関数で、これは対象のオブジェクトの存在が必要であり、メンバポインタ(メンバ関数ポインタ)の仕組みを用いる必要があります。
struct S {
int f(const char* str); // 静的でないメンバ関数の宣言
};
int (S::*fp)(const char*) = &S::f; // メンバポインタの宣言と初期化
S s {};
int ret = (s.*fp)("hello"); // メンバポインタを間接参照して関数を呼び出すC++ では、関数オブジェクトやラムダ式を用いることで、関数ポインタのような振る舞いが実現できます。
C++ の関数オブジェクトは、operator() を定義したクラスの実体です。関数オブジェクト自体は関数でも関数ポインタでもありませんが、関数であるかのように呼び出すことができます。C++ のラムダ式は、関数オブジェクトを簡潔に記述する構文です。
関数オブジェクトは、関数ポインタと異なり、データメンバによって状態を保持できることが特徴的です。
// 関数オブジェクト
struct FuncObj {
int operator()(const char* str) const {
return 123;
}
};
FuncObj fo {};
int ret1 {fo("hello")};
// ラムダ式
auto lambda = [](const char* str) -> int {
return 123;
};
int ret2 {lambda("hello")};C++ の関数ポインタ、関数オブジェクト、ラムダ式に関する詳細な解説は、新C++編「関数ポインタとラムダ式」メンバ関数ポインタについては「クラス」のページにあります。
Programming Place Plus のトップページへ
| はてなブックマーク に保存 | Facebook でシェア | X で ポスト/フォロー |
| LINE で送る | noteで書く |
|
| 管理者情報 | プライバシーポリシー |