函数对象有时也叫仿函数,它的本质是一个类对象。由于这个类重载了函数调用符号 (),它就可以像普通函数一样被使用。
1. operator() 重载
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;
}

冀公网安备13050302001966号