私は最近、C++ で「関数呼び出し」演算子をオーバーロードできることを発見しました。そのためには、2 対の括弧を書かなければならないという奇妙な方法があります。
class A {
int n;
public:
void operator ()() const;
};
そして、次のように使用します。
A a;
a();
これはいつ役に立ちますか?
私は最近、C++ で「関数呼び出し」演算子をオーバーロードできることを発見しました。そのためには、2 対の括弧を書かなければならないという奇妙な方法があります。
class A {
int n;
public:
void operator ()() const;
};
そして、次のように使用します。
A a;
a();
これはいつ役に立ちますか?
これは、関数のように機能するオブジェクトである「ファンクター」を作成するために使用できます。
class Multiplier {
public:
Multiplier(int m): multiplier(m) {}
int operator()(int x) { return multiplier * x; }
private:
int multiplier;
};
Multiplier m(5);
cout << m(4) << endl;
上記の印刷物20
。上にリンクされたウィキペディアの記事には、より実質的な例が示されています。
テンプレートを使い始めるまでは、operator() を使用することで得られるのは構文上の利点にすぎません。しかし、テンプレートを使用すると、実際の関数とファンクター (関数として機能するクラス) を同じように扱うことができます。
class scaled_sine
{
explicit scaled_sine( float _m ) : m(_m) {}
float operator()(float x) const { return sin(m*x); }
float m;
};
template<typename T>
float evaluate_at( float x, const T& fn )
{
return fn(x);
}
evaluate_at( 1.0, cos );
evaluate_at( 1.0, scaled_sine(3.0) );
テンプレートを使用して実装されたアルゴリズムは、呼び出されるものが関数であるかファンクターであるかを気にせず、構文を気にします。標準のもの (for_each() など) または独自のもの。また、ファンクターは状態を持つことができ、呼び出されたときにあらゆる種類のことを行うことができます。関数は、静的ローカル変数またはグローバル変数でのみ状態を持つことができます。
関数ポインターをカプセル化するクラスを作成している場合、これにより使用法がより明確になる可能性があります。