51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

C++ 函数对象

函数对象有时也叫仿函数,其本质是一个类对象,由于重载函数调用符号,其可以像普通函一样使用。

  1. 函数调用符号重载语法 {#title-0} ========================
class Demo
{
public:
	// 返回值:由自己来定义
	void operator()()
	{
		cout << "hello world" << endl;
	}

	int operator()(int a, int b)
	{
		return a + b;
	}
};

// 函数调用符号:(), C++支持对该运算符重载。类重载函数调用符号之后,就可以像普通函数一样调用了。
void test01()
{
	// 1.1 语法
	Demo demo1;
	demo1();  // demo1.operator()()
	cout << demo1(10, 20) << endl;  // demo1.operator()(10, 20)
	// 函数重载了函数调用符号之后,叫做函数对象,仿函数

	// 1.2 函数对象的赋值
	Demo demo2 = demo1;
	demo2();
	demo2(10, 20);

	function<void()> demo3 = demo1;
	demo3();
	function<int(int, int)> demo4 = demo1;
	cout << demo4(10, 20) << endl;
}
  1. 函数对象相对于普通函数的优点 {#title-1} ============================

C++中使用函数对象作为函数调用,而不是再使用函数指针。

  1. 函数对象本质是一个类,当调用函数对象时,实际执行的是成员函数。类内定义的函数自动成为内联函数。
  2. 函数对象是有类型的,可以使用类型再定义函数对象出来。但是,普通函数是没有类型,无法再创建出来函数。
  3. 函数对象本质上一个类,所以,其可以拥有成员,具有更加丰富表现能力。而普通函数不行: 统计函数调用次数
int cnt = 0;
void func()
{
	++cnt;
}

class Functor
{
public:
	Functor()
	{
		m_cnt = 0;
	}

	void operator()()
	{
		++m_cnt;
		show();
	}

	void show()
	{

	}

public:
	int m_cnt;
};
  1. lambda 和 函数对象 {#title-2} ===========================

lambda 是匿名的函数对象,本质上也是一个类对象,并不是简单的匿名普通函数。

void test02()
{
	auto f = []() {};
	cout << typeid(f).name() << endl;

	auto f1 = [](int a, int b) { cout << a << " " << b << endl; };
	/*
		class 随机名字
		{
		public:
			void operator()(int a, int b) const
			{
				cout << a << " " << b << endl;
			}
		}

		随机名字 对象;
	*/

	int num1 = 100;
	int num2 = 200;
	auto f2 = [=]() mutable { num1 = 100; };
	// lambda 表达式默认进行值捕获的时候,是无法修改,原因就是 operator() 函数是用 const 修饰
	/*
		class 随机名字
		{
		public:
			随机名字(int a, int b): num1(a), num2(b){}
			void operator()() const
			{
				num1 = 100;
			}
		public:
			mutable int num1;
			mutable int num2;
		}
	*/

	auto f3 = [&]() { num1 = 100; };
	/*
		class 随机名字
		{
		public:
			随机名字(): num1(num1), num2(num2){}
			void operator()() const
			{
				num1 = 100;
			}
		public:
			int &num1;
			int &num2;
		}
	*/

	auto ff1 = [=]() {};
	function<void()>  ff2 = [=]() {};

	// 下面这种方式无法进行外部变量捕获
	// 如果 lambda 捕获外部变量,则其必须以对象的形式存在。
	// 如果 Lambda 不捕获外部变量,该对象仅仅是独立可以运行的成员函数。
	void(*ff3)() = []() {};
	/*
	class 随机名字
		{
		public:
			void operator()() const
			{
				
			}
		}
	*/
}
  1. 函数对象使用举例 {#title-3} ======================
struct MyCompare
{
	bool operator()(int num1, int num2)
	{
		return num1 > num2;
	}
};


void test03()
{
	// C 语言中使用 qsort 函数排序
	// C++ 中使用 sort 函数排序

	int arr[] = { 9, 2, 1, 8, 4, 6, 5 };

	for (auto val : arr)
	{
		cout << val << " ";
	}
	cout << endl;

	// sort 函数前两个参数是一个区间,第一个元素的位置,最后一个元素的下一个位置
	sort(arr, &arr[6] + 1, MyCompare());

	for (auto val : arr)
	{
		cout << val << " ";
	}
	cout << endl;
}
赞(2)
未经允许不得转载:工具盒子 » C++ 函数对象