はい、できます:
型システムは少し複雑ですが。
したがって、通常、typedefで関数へのポインタをラップします。
typedef <returnType> (*<TypeName>)(<ParameterList>);
// In your case:
tpyedef void (*PtrToTimeFunc)();
// Now your pointer types look like normal variables:
PtrToTimeFunc pf = &PrintCurrentTimeStamp;
// Calling them is like normal:
pf(); // If it needed parameters then put them as normal.
C ++コンパイラは、コードを最適化するために関数ポインタを渡すことができないためです。C ++では、ファンクターを使用するのが一般的です。ファンクターは関数のように動作するオブジェクトですが、オブジェクトであるため、状態を含めることもできます(他の言語のクロージャのように)。
struct MyFunctor
{
// To make a functor just override the operator ()
// You can make it return any type and take any parameters (just like a function).
int operator()() const
{
return time(NULL);
}
// Add any state and constructors etc. you like here.
// Though note: because I declared the operator() as const you
// can not mutate the state via the function call (remove cost)
// if you want to do that.
};
// declaring a functor just like any-other object.
MyFunctor myFunctor;
// calling. Just like a function.
myFunctor();
わかった。では、なぜこれがポインタよりも役立つのでしょうか。
標準アルゴリズムで使用する場合。のタイプでアルゴリズムを定義するとfunctor
、コンパイラはアルゴリズムコードを生成し、ファンクタのすべてのコードも利用できるようになります(過去に最適化できない関数ポインタとは異なります)。これにより、コンパイラーは完全な最適化セットを適切に実行できます。
std::generate(cont.begin(), cont.end(), myFunctor);
そのため、C++11ではラムダを導入しました。これらは基本的に、その場で定義できる関数です。ただし、ラムダはコンパイラによって生成されたファンクタと考える方が簡単です(can
定義の一部として現在の状態をキャプチャするため)。
std::generate(cont.begin(), cont.end(), [](){return time(NULL);});
// [] - defines the state that is being captured.
// Think of this like the constructor capturing objects.
// In this case take no state.
//
// () - parameter list
// In this case no parameters
//
// {} - The code.
より興味深い例:
std::vector<int> data; // fill vector
std::for_each(data.begin(), data.end(), [](int& value){value += 4;}); // Add 4 to each member.