C++ Primer 5th笔记(chap 14 重载运算和类型转换)可调用对象与function

1. 5种形式

可调用对象有5种形式,类型各不同:

形式 解释
函数 返回值类型和实参类型
函数指针 返回值类型和实参类型
lambda表达式 类类型
bind创建的对象 todo
重载了函数调用运算符的类 类类型

2. 虽然可调用对象类型不同,但是调用形式可以一样

调用形式指明了调用返回的类型以及传递给调用的实参类型。不同的可调用对象可能具有相同的调用形式。

eg. 类型都为int(int, int)

// ordinary function
int add(int i, int j) {
    
     return i + j; }

//lambda表达式,其产生一个未命名的函数对象类
auto mod = [](int i, int j) {
    
     return i % j; };

// function-object class
struct divide
{
    
    
    int operator()(int denominator, int divisor)
    {
    
    
        return denominator / divisor;
    }
};

//调用代码
//使用map映射
map<string,function<int(int,int)> > binops;
binops.insert({
    
    "+", add});
//error,不能将mode或divide insert到binope中,因为他们类型不是函数指针
binops.insert({
    
    "%", mod});

有个问题:不能统一调用

3. 如何统一调用?

标准库function类型:标准库function类型是一个模板,定义在头文件functional中,用来表示对象的调用形式。
使用时需要创建一个具体的function类型。(必须提供其所表示的对象的调用形式)

操作 解释
function f; f是一个用来存储可调用对象的空function,这些可调用对象的调用形式应该与类型T相同。
function f(nullptr); 显式地构造一个空function
function f(obj) 在f中存储可调用对象obj的副本
f 将f作为条件:当f含有一个可调用对象时为真;否则为假。
定义为function的成员的类型f(args) 调用f中的对象,参数是args
result_type 该function类型的可调用对象返回的类型
argument_type 当T有一个或两个实参时定义的类型。
first_argument_type 第一个实参的类型
second_argument_type 第二个实参的类型

eg. function<int(int, int)>

function<int(int,int)> f1=add;  //函数指针
function<int(int,int)> f2=divide();  //函数对象类的指针
function<int(int,int)> f3=[](int i,int l){
    
    return i*j;};  //lambda
                                   
cout << f1(4,2) << endl;   // prints 6
cout << f2(4,2) << endl;   // prints 2
cout << f3(4,2) << endl;   // prints 8

eg2.

//使用map映射
map<string,function<int(int,int)> > binops={
    
    
    {
    
    "+",add},  //函数指针
    {
    
    "-",std::minus<int>()},  //标准库函数对象
    {
    
    "/",divide()},  // 用户定义的函数对象
    {
    
    "*",[](int i,int j){
    
    return i*j;}},  //未命名的lambda
    {
    
    "%",mod} //已命名的lambda对象
};

//这个时候insert是可以的 
binops.insert( {
    
    "+", add} );	//函数指针
binops.insert( {
    
    "/",divide()} );	//函数对象
binops.insert( {
    
    "%", mod} );	//lambda表达式
binops.insert({
    
    "+"},[](int a,in b){
    
    return add(a,b);});//lambda表达式
binops.insert({
    
     "add" , [](int a, int b) {
    
    return add(a, b); } });//lambda表达式

cout << binops["+"](10, 5)<<endl;//调用add(10, 5)
cout << binops["-"](10, 5) << endl;
cout << binops["/"](10, 5) << endl;	//使用divide对象调用括号运算符
cout << binops["*"](10, 5) << endl;
cout << binops["%"](10, 5) << endl;//调用lambda函数对象
cout << binops["add"](10, 5) << endl;//调用lambda函数对象    

3.1 不能直接将重载函数的名字存入 function 类型的对象中,这样做会产生二义性错误。

int add(int i,int j){
    
    return i + j;}
Sales_data add(const Sales_data&,const Sales_data&);
map<string,funciton<int(int,int)>> binops;
binops.insert({
    
    "+",add});		//错误,不能区分是哪个add 

3.2 解决方法

存储函数指针而非函数名字:

int (*fp) (int,int) = add;
binops.insert("add",fp);	//正确,fp指向正确的add版本
  • C++11新标准库中的function类与旧版本中的unary_function和binary_function没有关系,后两个类已经被bind函数代替。

【引用】

[1] 代码functionObject.h

猜你喜欢

转载自blog.csdn.net/thefist11cc/article/details/114166651