C++ Improved Programming 4: STL-Function Object

1. Function object (functor)

1.1. Concept of function object

concept:

  • A class that overloads the function call operator () , and its object is often called a function object
  • When a function object uses overloaded (), it behaves like a function call, also called a functor.

Nature:

A function object (functor) is a class , not a function

1.2. Use of function objects

Features:

  • When a function object is used, it can be called like a normal function, with parameters and return values.
  • Function objects go beyond the concept of ordinary functions. Function objects can have their own state.
  • Function objects can be passed as arguments
#include <iostream>
using namespace std;
#include <string>

//函数对象 (仿函数)

//● 函数对象在使用时,可以像普通函数那样调用, 可以有参数,可以有返回值
//● 函数对象超出普通函数的概念,函数对象可以有自己的状态
//● 函数对象可以作为参数传递

//1、函数对象在使用时,可以像普通函数那样调用, 可以有参数,可以有返回值
class MyAdd
{
public:
	int operator()(int v1, int v2)
	{
		return v1 + v2;
	}
};

void test01()
{
	MyAdd myAdd;
	cout << myAdd(10, 10) << endl;
}

//2、函数对象可以有自己的状态
class MyPrint
{
public:
	MyPrint()
	{
		count = 0;
	}
	void operator()(string test)
	{
		cout << test << endl;
		count++; //统计使用次数
	}

	int count; //内部自己的状态
};
void test02()
{
	MyPrint myPrint;
	myPrint("hello world");
	myPrint("hello world");
	myPrint("hello world");
	cout << "myPrint调用次数为: " << myPrint.count << endl;
}

//3、函数对象可以作为参数传递
void doPrint(MyPrint& mp, string test)
{
	mp(test);
}

void test03()
{
	MyPrint myPrint;
	doPrint(myPrint, "Hello C++");
}

int main()
{
	//test01();
	//test02();
	test03();
	system("pause");
	return 0;
}

Summary : Functor writing is very flexible and can be passed as parameters.

2. Predicate

2.1. Predicate concept

concept:

  • Functors that return bool type are called predicates
  • If operator() accepts one parameter, it is called a unary predicate
  • If operator() accepts two parameters, it is called a binary predicate

2.2. Unary predicate

#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>

//仿函数——返回值类型是bool数据类型,称为谓词

//1.一元谓词
class GreaterFive 
{
public:
	bool operator()(int val) {
		return val > 5;
	}
};

void test01() {

	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}

	//查找容器中  有没有大于5的数字
	//GreaterFive() 匿名函数对象
	vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());
	if (it == v.end()) {
		cout << "没找到!" << endl;
	}
	else {
		cout << "找到:" << *it << endl;
	}
}

int main() 
{
	test01();
	system("pause");
	return 0;
}

Summary : A predicate with only one parameter is called a unary predicate

Extension: find_if is used to find whether there is data that meets the conditions according to conditions (requires the first parameter, the last parameter and the predicate) and the algorithm header file needs to be addedalgorithm

2.3. Binary predicate

#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>

//二元谓词

class MyCompare
{
public:
	bool operator()(int num1, int num2)
	{
		return num1 > num2;
	}
};

void test01()
{
	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 << " ";
	}
	cout << endl;
	cout << "----------------------------" << endl;

	//使用函数对象改变算法策略,排序从大到小
	sort(v.begin(), v.end(), MyCompare());
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

int main() 
{
	test01();
	system("pause");
	return 0;
}

Summary : A predicate with only two is called a binary predicate

3. Built-in function objects

3.1. Meaning of built-in function objects

concept:

  • STL has some built-in function objects

Classification:

  • arithmetic functor
  • Relation functor
  • logical functor

usage:

  • The objects generated by these functors can be used exactly the same as ordinary functions.
  • To use built-in function objects, you need to introduce the header file #include<functional>

3.2. Arithmetic functor

Function description :

  • Implement four arithmetic operations
  • Among them, negate is a unary operation, and the others are binary operations.

Functor prototype:

  • template<class T> T plus<T>//addition functor
  • template<class T> T minus<T>//Subtraction functor
  • template<class T> T multiplies<T>//Multiplication functor
  • template<class T> T divides<T>//division functor
  • template<class T> T modulus<T>//Get the imitation function
  • template<class T> T negate<T>//Get the inverse function
#include <iostream>
using namespace std;
#include <functional>

//内建函数对象  算数仿函数

//negate  一元仿函数  取反仿函数
void test01()
{
	negate<int> n;
	cout << n(50) << endl;
}

//plus  二元仿函数  加法仿函数
void test02()
{
	plus<int> p;
	cout << p(10, 20) << endl;
}

int main()
{
	test01();
	test02();
	system("pause");
	return 0;
}

Summarize:

  • When using built-in function objects, you need to introduce the header file#include <functional>
  • Just write a parameter type in the template parameter list, because it only allows the same type of data to be processed.

3.3. Relation functor

Function description:

  • Realize relationship comparison

Functor prototype:

  • template<class T> bool equal_to<T>//equal
  • template<class T> bool not_equal_to<T>//not equal to
  • template<class T> bool greater<T>//more than the
  • template<class T> bool greater_equal<T>//greater or equal to
  • template<class T> bool less<T> //Less than
  • template<class T> bool less_equal<T>//less than or equal to
#include <iostream>
using namespace std;
#include <functional>
#include <vector>
#include <algorithm>

//内建函数对象  关系仿函数

class MyCompare
{
public:
	bool operator()(int v1, int v2)
	{
		return v1 > v2;
	}
};
void test01()
{
	vector<int> v;

	v.push_back(10);
	v.push_back(30);
	v.push_back(50);
	v.push_back(40);
	v.push_back(20);

	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	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 << " ";
	}
	cout << endl;
}

int main() 
{
	test01();
	system("pause");
	return 0;
}

Summarize:

The most commonly used relational functor is greater<>greater than

Sorting can use your own functor, or you can use the STL built-in functor.

3.4. Logic functor

Function description:

  • Implement logical operations

Function prototype:

  • template<class T> bool logical_and<T>//Logical AND
  • template<class T> bool logical_or<T> //logical or
  • template<class T> bool logical_not<T>//logical negation
#include <iostream>
using namespace std;
#include <vector>
#include <functional>
#include <algorithm>

//内建函数对象  逻辑仿函数
//逻辑非  logical_not

void test01()
{
	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() 
{
	test01();
	system("pause");
	return 0;
}

Summary : Logic functors have few practical applications, just understand them

(Note: Be sure to specify the capacity of another container when moving, because we did not insert data, but moved it directly. If the capacity is not specified, there will be no space)

expand:

The transform() function moves the beginning to the end of the first container to the second container, and performs the logical negation operation from the beginning of the second container.

Guess you like

Origin blog.csdn.net/qq_63388834/article/details/134969418