Cで関数をパラメーターとしてどのように渡しますか?

宣言

関数パラメータを取る関数のプロトタイプは次のようになります:

void func ( void (*f)(int) );

これは、パラメータ fvoid を持つ関数へのポインタになります 戻り値の型で、単一の int を取ります パラメータ。次の関数 (print ) は func に渡すことができる関数の例です 適切な型であるため、パラメーターとして:

void print ( int x ) {
  printf("%d\n", x);
}

関数呼び出し

関数パラメーターを指定して関数を呼び出す場合、渡される値は関数へのポインターである必要があります。これには関数の名前 (括弧なし) を使用します:

func(print);

func を呼び出します 、それに print 関数を渡します。

関数本体

他のパラメータと同様、func 関数本体でパラメーターの名前を使用して、パラメーターの値にアクセスできるようになりました。 func としましょう 渡された関数を 0 ~ 4 の数値に適用します。最初に、print を直接呼び出す場合のループを考えてみましょう:

for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
  print(ctr);
}

func以降 のパラメーター宣言は、 f と言っています は目的の関数へのポインタの名前です。最初に、f の場合を思い出してください。 *f の場合はポインタです f というものです を指す (つまり、関数 print この場合)。結果として、上記のループ内のすべての print を *f に置き換えるだけです。 :

void func ( void (*f)(int) ) {
  for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
    (*f)(ctr);
  }
}

ソース


この質問には、関数ポインターを定義するための答えが既にありますが、特にアプリケーションでポインターを渡す場合は、非常に面倒になる可能性があります。この不快感を避けるために、関数ポインターをより読みやすいものに型定義することをお勧めします。例えば。

typedef void (*functiontype)();

void を返し、引数を取らない関数を宣言します。この型への関数ポインタを作成するには、次のようにします:

void dosomething() { }

functiontype func = &dosomething;
func();

int を返し、char を受け取る関数の場合は、

typedef int (*functiontype2)(char);

そしてそれを使う

int dosomethingwithchar(char a) { return 1; }

functiontype2 func2 = &dosomethingwithchar
int result = func2('a');

関数ポインタを読みやすい型に変換するのに役立つライブラリがあります。ブースト関数ライブラリは素晴らしく、努力する価値があります!

boost::function<int (char a)> functiontype2;

上記よりもはるかに優れています。


C++11 以降、関数型ライブラリを使用して、簡潔で一般的な方法でこれを行うことができます。構文は、たとえば、

std::function<bool (int)>

ここで bool 最初の引数が int 型である引数が 1 つの関数の戻り値の型です。 .

サンプル プログラムを以下に示します:

// g++ test.cpp --std=c++11
#include <functional>

double Combiner(double a, double b, std::function<double (double,double)> func){
  return func(a,b);
}

double Add(double a, double b){
  return a+b;
}

double Mult(double a, double b){
  return a*b;
}

int main(){
  Combiner(12,13,Add);
  Combiner(12,13,Mult);
}

ただし、テンプレート関数を使用する方が便利な場合もあります:

// g++ test.cpp --std=c++11

template<class T>
double Combiner(double a, double b, T func){
  return func(a,b);
}

double Add(double a, double b){
  return a+b;
}

double Mult(double a, double b){
  return a*b;
}

int main(){
  Combiner(12,13,Add);
  Combiner(12,13,Mult);
}