STL関数オブジェクト
1. STL関数オブジェクト
1.1 関数オブジェクトの概念
コンセプト:
- 関数呼び出し演算子をオーバーロードするクラス。そのオブジェクトは関数オブジェクトと呼ばれることがよくあります。
- 関数オブジェクトがオーバーロード () を使用すると、** とも呼ばれる関数呼び出しのように動作します。ファンクタ**
自然:
- 関数オブジェクト (ファンクター) は **親切**、関数ではありません
1.2 関数オブジェクトの使用
特徴:
- 関数オブジェクトを使用すると、通常の関数と同じように呼び出すことができ、パラメータを指定したり、戻り値を指定したりできます。
- 関数オブジェクトは通常の関数の概念を超え、関数オブジェクトは独自の状態を持つことができます
- 関数オブジェクトは引数として渡すことができます
コード例:
#include<iostream>
using namespace std;
#include<string>
// 1. 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
class MyAdd
{
public:
int operator()(int v1, int v2)
{
return v1 + v2;
}
};
void test_01()
{
MyAdd myAdd;
cout << myAdd(10, 10) << endl; // 20
}
// 2. 函数对象可以有自己的状态
class MyPrint
{
public:
MyPrint()
{
count = 0;
}
void operator()(string test)
{
cout << test << endl;
count++; // 统计使用的次数
}
int count; // 内部自己的状态
};
void test_02()
{
MyPrint myPrint;
myPrint("hello world");
myPrint("hello world");
myPrint("hello world");
cout << "myPrint调用次数为:" << myPrint.count << endl; // myPrint调用次数为: 3
}
// 3. 函数对象可以作为参数传递
void doPrint(MyPrint& mp, string test)
{
mp(test);
}
void test_03()
{
MyPrint myPrint;
doPrint(myPrint, "Hello C++"); // Hello C++
}
int main()
{
test_01();
test_02();
test_03();
system("pause");
return 0;
}
2. 述語
2.1 述語の概念
コンセプト:
- bool 型を返すファンクターは ** と呼ばれます述語**
- Operator() が 1 つの引数を取る場合、それは単項述語と呼ばれます
- Operator() が 2 つの引数を取る場合、それはバイナリ述語と呼ばれます
2.2 述語の使用
コード例:
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
struct GreaterFive
{
bool operator() (int val)
{
return val > 5;
}
};
// 一元谓词
void test_01()
{
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());
if (it == v.end())
{
cout << "没找到!" << endl;
}
else
{
cout << "找到:" << *it << endl; // 找到:6
}
}
// 二元谓词
class MyCompare
{
public:
bool operator()(int num1, int num2)
{
return num1 > num2;
}
};
void test_02()
{
vector<int>v;
v.push_back(10);
v.push_back(40);
v.push_back(20);
v.push_back(30);
v.push_back(50);
// 标准算法排序--默认从小到大
sort(v.begin(), v.end());
for (vector<int>::iterator it = v.begin(); it!=v.end(); it++)
{
cout << *it << " "; // 10 20 30 40 50
}
cout << endl;
cout << "--------------------------------------" << endl;
// 使用函数对象,改变算法策略,变为排序规则从大到小
sort(v.begin(), v.end(), MyCompare());
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " "; // 50 40 30 20 10
}
cout << endl;
}
int main()
{
test_01();
test_02();
system("pause");
return 0;
}
3. 組み込み関数オブジェクト
3.1 組み込み関数オブジェクトの意味
コンセプト:
- STL にはいくつかの組み込み関数オブジェクトがあります
分類:
- 算術関数
- 関係関数
- 論理関数
使用法:
- これらのファンクターによって生成されたオブジェクトは、通常の関数とまったく同じ方法で使用されます。
- 組み込み関数オブジェクトを使用するには、ヘッダー ファイル #include<function> を導入する必要があります。
3.2 算術関手
機能の説明:
- 4つの操作を実現
ファンクターのプロトタイプ:
- template<class T> T plus<T> // 加算関数
- template<class T> Tminus<T> // 減算関数
- template<class T> T multiplies<T> // 乗算関数
- template<class T> T Divisions<T> // 除算関数
- template<class T> T modulus<T> // 模倣関数を取得します
- template<class T> T negate<T> // 否定関数子
コード例:
#include<iostream>
using namespace std;
#include<functional>
void test_01()
{
negate<int> n;
cout << n(50) << endl; // -50
}
void test_02()
{
plus<int> p;
cout << p(10, 20) << endl; // 30
}
int main()
{
test_01();
test_02();
system("pause");
return 0;
}
3.3 関係関数
機能の説明:
- 関係比較を実現する
ファンクターのプロトタイプ:
- template<class T> boolqual_to<T> // 等価
- template<class T> bool not_equal_to<T> // 等しくない
- template<class T> boolgreater<T> // より大きい
- template<class T> bool great_equal<T> // 以上
- template<class T> boolless<T> // 小より
- template<class T> bool less_equal<T> // 以下
コード例:
#include<iostream>
using namespace std;
#include<functional>
#include<vector>
#include<algorithm>
class MyCompare{
public:
bool operator()(int v1, int v2)
{
return v1 > v2;
}
};
void test_01()
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
for (vector<int>::iterator it=v.begin(); it!=v.end(); it++)
{
cout << *it << " "; // 10 20 30 40
}
cout << endl;
// 自己实现仿函数
// sort(v.begin(), v.end(), MyCompare());
// STL内建仿函数 大于仿函数
sort(v.begin(), v.end(), greater<int>());
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << endl; // 40 30 20 10
}
cout << endl;
}
int main()
{
test_01();
system("pause");
return 0;
}
3.4 論理関数
機能の説明:
- 論理演算の実装
関数プロトタイプ:
- template<class T> boollogical_and<T> // 論理積
- template<class T> boollogical_or<T> // 論理和
- template<class T> boollogical_not<T> // 非
#include<iostream>
using namespace std;
#include<functional>
#include<vector>
#include<algorithm>
void test_01()
{
vector<bool> v;
v.push_back(true);
v.push_back(false);
v.push_back(true);
v.push_back(false);
for (vector<bool>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
// 逻辑非 将v容器搬运到v2中,并执行逻辑非运算
vector<bool> v2;
v2.resize(v.size());
transform(v.begin(), v.end(), v2.begin(), logical_not<bool>());
for (vector<bool>::iterator it = v2.begin(); it != v2.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
test_01();
system("pause");
return 0;
}