C++学习——函数调用运算符、function类模板

一、函数调用运算符

1、圆括号()就是函数调用的明显标记,()有一个称呼叫做“函数调用运算符”;

2、如果我在类中重载了函数调用运算符,那么我们就可以像使用函数一样使用该类的对象了。对象(实参):

class BiggerThanZero
{
public:
    //重载圆括号(函数调用运算符)
    int operator()(int value) const
    {
    	if (value < 0)
    		return 0;
    	return value;
    }
};

int main()
{
    int i = 200;
    BiggerThanZero obj;
    int result = obj(i);//等价于obj.operator()(i);
    //int result = obj.operator()(i);
    cout << result << endl;
    return 0;
}

2、对象(实参)有点似曾相识,那就是有参构造函数:

class BiggerThanZero
{
public:
    //重载圆括号(函数调用运算符)
    BiggerThanZero(int i){};//有参构造函数
    int operator()(int value) const
    {
    	if (value < 0)
    		return 0;
    	return value;
    }
};

int main()
{
    int i = 200;
    BiggerThanZero obj(i);//这是对象定义并初始化,所以调用的是构造函数,并没有调用重载的()
    int result = obj(i);//等价于obj.operator()(i);
    //int result = obj.operator()(i);
    cout << result << endl;
    return 0;
}

3、结论:

      1)只要这个对象所属的类重载了()(函数调用运算符),那么这个类对象就变成了可调用的勒,而且可以调用多个版本的(),只要在参数类型或者数量上有差别即可;

class BiggerThanZero
{
public:
    //重载圆括号(函数调用运算符)
    BiggerThanZero(int i){};//有参构造函数
    int operator()(int value) const //重载() 1
    {
    	if (value < 0)
    		return 0;
    	return value;
    }
    int operator()(int value, char c) const//重载() 2
    {
    	if (value < 0)
    		return 0;
    	return value;
    }
    int operator()(int value, char c, int value1) const//重载() 3
    {
    	if (c < 0)
    		return 0;
    	return c;
    }
};

      2)这个类重载了(),那么该类的对象就多了个新名字,叫“函数对象”,因为可以调用这种对象。或者换一种说法:这些对象的行为像函数一样;

4、不同调用对象的相同调用形式(如下echoValue函数与BiggerThanZero类中的operator()就叫做调用形式相同):

class BiggerThanZero
{
public:
    int operator=(int value) const
    {
    	cout << "class value : " << value << endl;
    	if(value < 0)
    		return 0;
    	return value;
    }
};

int echoValue(int value)//调用参数和返回值与BiggerThanZero类中的operator()成员相同
{
    cout << "echoValue : " << value << endl;
    if(value < 0)
    	return 0;
    return value;
}

      1)函数echoValue和类BiggerThanZero的重载(),这两个东西的调用参数和返回值相同,我们可以称之为“调用形式相同”;
      2)一种调用形式对应一个函数类型,如int(int) 表示接受一个int参数和返回一个int值;
  5、可调用对象
      1)如下两种实现都是可调用对象:
             a)echoValue函数;
             b)重载了函数调用运算符的BiggerThanZero类对象;

      2)把这些可调用对象的指针保存起来,目的是方便我们随时调用这些“可调用对象”,这些指针感觉像我们C语言中的函数指针;

int (*p)(int x);//p就是定义的指针变量
p = max;//函数max的入口地址给p
int result = p(5);//调用函数max 等价于 max(5);

三、标准库map类型介绍

1、map是一个类模板,头文件#include <map>;

2、Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据 处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一 种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。

3、map是一类关联式容器。它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。

对于迭代器来说,可以修改实值,而不能修改key。

4、用法:

map<int, string> mapStudent;

5、数据的插入:

      1)用insert函数插入pair数据

//数据的插入--第一种:用insert函数插入pair数据  
#include <map>  
#include <string>   
#include <iostream>    
using namespace std;  
      
int main()      
{  
    map<int, string> mapStudent;  

    mapStudent.insert(pair<int, string>(1, "student_one"));  
    mapStudent.insert(pair<int, string>(2, "student_two"));  
    mapStudent.insert(pair<int, string>(3, "student_three"));  
    map<int, string>::iterator iter;  
      
    for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)  
        cout<<iter->first<<' '<<iter->second<<endl;  
    return 0;
}  

      2)用insert函数插入value_type数据:

//第二种:用insert函数插入value_type数据,下面举例说明      
#include <map>  
#include <string>  
#include <iostream>  
using namespace std;  
      
int main()  
{  
    map<int, string> mapStudent;  
    
    mapStudent.insert(map<int, string>::value_type (1, "student_one"));  
    mapStudent.insert(map<int, string>::value_type (2, "student_two"));  
    mapStudent.insert(map<int, string>::value_type (3, "student_three"));  
    map<int, string>::iterator iter;  
    for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)  
        cout<<iter->first<<' '<<iter->second<<endl;  
    return 0;     
}  

      3)用数组方式插入数据:

//第三种:用数组方式插入数据,下面举例说明
#include <map>
#include <string>
#include <iostream>
using namespace std;
 
int main()
{
    map<int, string> mapStudent;
 
    mapStudent[1] = "student_one";
    mapStudent[2] = "student_two"; 
    mapStudent[3] = "student_three";

    map<int, string>::iterator iter; 
    for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
        cout<<iter->first<<' '<<iter->second<<endl;
    return 0;
}

6、注意:以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,用insert函数插入数据,在数据的 插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是插入数据不了的,但是用数组方式就不同了,它可以覆盖以前该关键字对 应的值;

7、参考博客:C++ STL 中 map 容器的说明和使用技巧

四、标准库function类型介绍

1、function是一个类模板,头文件#include <functional>;

2、function类模板,要提供模板参数来表示该function类型能够表示的“对象的调用形式”,类模板std :: function是一个通用的多态函数包装器, std :: function的实例可以存储,复制和调用任何可调用的目标 :包括函数,lambda表达式,绑定表达式或其他函数对象,以及指向成员函数和指向数据成员的指针。当std::function对象未包裹任何实际的可调用元素,调用该std::function对象将抛出std::bad_function_call异常;

template< class R, class... Args >
class function<R(Args...)>;
模板参数说明:
    R: 被调用函数的返回类型
    Args…:被调用函数的形参

function<int(int)>//声明了一个function()类型,用来代表一个可调用对象,它所代表的这个可调 
                  //用对象是:接受一个int参数,返回一个int类型;

五、可调用对象的使用

class BiggerThanZero
{
public:
    int operator=(int value) const
    {
    	cout << "class value : " << value << endl;
    	if(value < 0)
    		return 0;
    	return value;
    }
};

int echoValue(int value)//调用参数和返回值与BiggerThanZero类中的operator()成员相同
{
    cout << "echoValue : " << value << endl;
    if(value < 0)
    	return 0;
    return value;
}

int main()
{
    map<string, function<int(int)>> myoper = {
        {"a1", echoValue},
        {"a2", obj},
        {"a3", BiggerThanZero}
    };

    myoper["a1"](12);//调用echoValue函数
    myoper["a2"](13);//调用obj对象的operator()函数
    myoper["a3"](14);//调用BiggerThanZero类重载()函数
    
    return 0;
}

1、一旦function遇到echoValue的重载版本就无法识别,编译不通过;

int echoValue(int value)//调用参数和返回值与BiggerThanZero类中的operator()成员相同
{
    cout << "echoValue : " << value << endl;
    if(value < 0)
    	return 0;
    return value;
}

int echoValue()
{
    return 1;
}

int main()
{
    map<string, function<int(int)>> myoper = {
        {"a1", echoValue};//编译报错
    };
    
    return 0;
}

      解决:我们可以通过定义函数指针类解决,如下:

int (*fp)(int) = echoValue;
int (*fp1)() = echoValue;

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值