我们把“()”叫做函数调用运算符,因为我们就是使用“()”来调用函数的。
在类中我们可以重载这个符号“()”,这样就可以像调用函数对象一样调用类的对象,这种重载了"()"的对象就是函数对象。
比如定义一个函数对象来求int的绝对值:
struct absInt{
//重载"()"的方法只能定义为成员函数,即只能定义在类内部不能定义在类外部
int operator()(int val) const{//后面的const表示该方法只能读取成员变量,不能改变成员变量
return val<0?-val:val;
}
}
int i = -10;
absInt abs;
int rel = abs(-10);//像调用方法一样调用函数对象
lambda表达式也是函数对象,编译器会将lambda表达式翻译成一个未命名类的未命名对象。
c++的标准库中定义了一些功能函数对象的类,可以直接使用,比如一个执行加法功能的函数对象:
#include <functional>
std::plus<int> p;
int val = p(10,10);
函数的类型用它的返回值和参数确定,而函数对象的类型就是这个函数对象对应声明的类,所以就算两个返回值和参数都是一样的函数和函数对象都是不一样的。如:
int intAbsFun(int val)
{
return val >= 0 ? val : -val;
}
struct intAbs
{
int operator()(int val) const
{
return val >= 0 ? val : -val;
}
};
std::vector<int (*)(int)> absList;
absList.push_back(intAbsFun);
intAbs abs;
absList.push_back(abs);//这里会报错,因为abs的类型是intAbs
在新标准中我们可以使用function来解决这个问题,这个function可以将具有相同的返回值和参数的可使用调用运算符的对象统一为一个类型,如上面的函数和函数对象可以这样统一:
#include <functional>
std::vector<std::function<int(int)>> absList;//将类型定义为std::function<int(int)>即可
absList.push_back(intAbsFun);
intAbs abs;
absList.push_back(abs);
std::cout << absList[1](-10) << std::endl;