オーバーロード () を理解する前に、まず C++ の関数オブジェクトの概念を理解する必要があります。
1. 関数オブジェクトとは何ですか?
FunctionObject 型は、関数呼び出し演算子の左側で使用できるオブジェクトの型です。
つまり、関数オブジェクト タイプは、関数呼び出し演算子の左側で使用できるオブジェクト タイプです (追記: 括弧 () です)。
ドキュメントによると、いくつかのタイプの関数オブジェクトを要約できます。
- 関数または関数参照 (暗黙的な変換が必要)
- 関数ポインタ
- < function > ヘッダー ファイルで定義されているすべての関数オブジェクト (less、greater など)
- < function > ヘッダー ファイル内の一部の関数の戻り値
注
関数および関数への参照は関数オブジェクト型ではありませんが、関数からポインターへの暗黙的な変換
により、関数オブジェクト型が予期される場所で使用できます。標準ライブラリ
関数へのすべてのポインターはこの要件を満たします。
< 関数 > で定義されたすべての関数オブジェクト
< 関数 > の関数の一部の戻り値の型
さらに:
5. ラムダ式 (C++11 以降)
6. 関数呼び出し演算子 () をオーバーロードするクラスのオブジェクト
C++ では、カスタム比較関数のうち、一般的な受信関数名、またはそれ以下のオブジェクト、またはそれ以上のオブジェクトがこの種の関数オブジェクトに属します。ただし、次のようなものは暗黙的な型変換を行います。(具体的な変換プロセスについては見ていません。明確なメッセージがある場合は、メッセージを残してください)
// 传入函数名
vector<int> vec;
bool cmp(const pair<int, int>& A. const pair<int, int>& B) {
return A.second < B.second;
}
sort(vec.begin(), vec.end(), cmp);
以下に、関数オブジェクト (関数ポインター、関数呼び出し演算子 () をオーバーロードするクラスのオブジェクト、
ラムダ式)のその他の使用例をいくつか示します。
#include <iostream>
void foo(int x) {
std::cout << "foo(" << x << ")\n"; }
int main()
{
void(*fp)(int) = foo;
fp(1); // calls foo using the pointer to function
struct S {
void operator()(int x) const {
std::cout << "S::operator(" << x << ")\n"; }
} s;
s(2); // calls s.operator()
s.operator()(3); // the same
auto lam = [](int x) {
std::cout << "lambda(" << x << ")\n"; };
lam(4); // calls the lambda
lam.operator()(5); // the same
}
2. オーバーロードされた関数呼び出し演算子 () 括弧
括弧は関数呼び出し演算子です。
() 括弧のオーバーロード、つまり関数呼び出し演算子のオーバーロード。
ユーザー定義クラスのオーバーロードされた関数が Operator() を呼び出すと、その関数は FunctionObject 型になります。FunctionObject 型は関数として呼び出すことができ、この型のオブジェクトは関数呼び出し式で使用できます。
これは少しわかりにくいかもしれませんが、次の例は理解しやすいでしょう。
// An object of this type represents a linear function of one variable a * x + b.
struct Linear
{
double a, b;
double operator()(double x) const
{
return a * x + b;
}
};
int main()
{
Linear f{
2, 1}; // Represents function 2x + 1.
Linear g{
-1, 0}; // Represents function -x.
// f and g are objects that can be used like a function.
double f_0 = f(0);
double f_1 = f(1);
double g_0 = g(0);
}
オーバーロードされた関数呼び出し演算子 () の後のクラスは、関数オブジェクト (FunctionObject) クラスの機能を備えた関数オブジェクト (FunctionObject) クラスであり、インスタンス化されたオブジェクトは、この記事の最初のセクションで紹介したオブジェクトです。
参考文献:
- https://en.cppreference.com/w/cpp/named_req/FunctionObject
- https://en.cppreference.com/w/cpp/ language/
operators 2 番目のリンクについては、「関数呼び出し演算子」セクションを参照してください。これら 2 つのドキュメントは非常によく書かれており、強くお勧めします。