C++函数对象与可调用对象

重载函数调用运算符

如果类重载了函数调用运算符,则我们可以像使用函数一样使用该类的对象,因为这样的类同时也能存储状态,所以与普通函数相比它们更加灵活,例如下面的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");
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容