函数对象有时也叫仿函数,其本质是一个类对象,由于重载函数调用符号,其可以像普通函一样使用。
1. 函数调用符号重载语法
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; }
2. 函数对象相对于普通函数的优点
C++中使用函数对象作为函数调用,而不是再使用函数指针。
- 函数对象本质是一个类,当调用函数对象时,实际执行的是成员函数。类内定义的函数自动成为内联函数。
- 函数对象是有类型的,可以使用类型再定义函数对象出来。但是,普通函数是没有类型,无法再创建出来函数。
- 函数对象本质上一个类,所以,其可以拥有成员,具有更加丰富表现能力。而普通函数不行: 统计函数调用次数
int cnt = 0; void func() { ++cnt; } class Functor { public: Functor() { m_cnt = 0; } void operator()() { ++m_cnt; show(); } void show() { } public: int m_cnt; };
3. lambda 和 函数对象
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 { } } */ }
4. 函数对象使用举例
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; }