重载函数调用运算符
如果类重载了函数调用运算符,则我们可以像使用函数一样使用该类的对象,因为这样的类同时也能存储状态,所以与普通函数相比它们更加灵活,例如下面的PrintString可以定制用于输出的流以及分隔符。
函数调用运算符必须是成语函数,一个类可以定义多个不同版本的调用运算符,相互之间应该在参数数量或类型上有所区别。
当我们编写一个lambda后,编译器将该表达式翻译成一个未命名类的未命名对象,该类中含有一个重载的函数调用运算符。
class PrintString
{
public:
PrintString(std::ostream& os, char c) :os_(os), sep_(c) {};
void operator()(const std::string& str) const
{
os_ << str << sep_;
}
private:
std::ostream& os_;
char sep_;
};
int main()
{
PrintString printObj{ std::cout, ',' };
printObj("hello");
printObj("world");
system("pause");
}
标准库函数对象
标准库定义了一组表示算术运算符,关系运算符和逻辑运算符的类,每个类分别定义了一个执行命名操作的调用运算符,例如plus类定义了一个函数调用符用于对一对运算对象执行+的操作,这些类都被定义为模板的形式,我们可以为其指定具体的类型。
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> values{ 1,100,20,50,30 };
std::sort(values.begin(), values.end(), std::greater<int>());
for (const auto& value : values) {
std::cout << value << std::endl;
}
system("pause");
}
可调用对象
C++中有几种可调用的对象,函数,函数指针,lambda表达式,bind创建的对象,重载了函数调用运算符的类,这些不同类型的可调用对象可能共享同一种调用形式,例如int(int,int),我们可以使用function来表示这种调用形式。
#include <iostream>
#include <vector>
#include <functional>
int myAddFunction(int a, int b)
{
return a + b;
}
int main()
{
using AddFunction = std::function<int(int,int)>;
auto lambdaFunc = [](int a, int b) {return a + b; };
std::vector<AddFunction> values{myAddFunction,std::plus<int>(),lambdaFunc};
for (const auto& value : values) {
std::cout << value(1, 1) << std::endl;
}
system("pause");
}