C++语法学习笔记二十四:函数调用运算符、function类模板

实例代码:


#include <iostream>
#include <string>
#include <vector>

#include <map>
#include <functional>


using namespace std;

void func(int i){
	cout << "这是函数func()" << endl;
	return;
}

//下面类重载()运算符
//如果值 < 0,那么就返回0,否则返回实际的值
class biggerthanzero{
public:
	//重载圆括号(函数调用运算符)
	int operator()(int value) const{
		if (value < 0)
			return 1;
		return value;
	}

};


class biggerthanzero1{
public:
	biggerthanzero1(int){
		cout << "bigg...构造函数执行了" << endl;
	}

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

	//重载圆括号(函数调用运算符)
	int operator()(int value, int value1) const{
		return 1;
	}
};

//普通函数:打印value值并原样返回
int echobvalue(int value) { //调用参数和返回值与biggerthanzero1中的operator()相同
	cout << value << endl;
	return value;
}


int echobvalue1(int value) { //调用参数和返回值与biggerthanzero1中的operator()相同
	cout << value << endl;
	return value;
}

int echobvalue1() { //调用参数和返回值与biggerthanzero1中的operator()相同
	return 1;
}


int main() {

	//一:学习C++体会
	//(1) 对语言本身的学习
	//(2) 大量练习
	//(3) 开始阅读优秀的人写的优秀代码

	func(5);
	//圆括号()就是函数调用的明显标记,()有一个称呼叫做“函数调用运算符”;
	//如果我在类中重载了函数调用运算符(),那么我就可以像使用函数一样使用该类的对象了。如:“ 对象(实参)” 这种形式

	//如何使用类中重载了函数调用运算符()的类呢?
	//(a) 定义一个该类对象
	//(b) 像函数调用一样使用该对象,也就是()中增加实参列表。
	int i = 200;
	biggerthanzero obj; //含有函数调用运算符的对象。
	int result = obj(i);  //等价于调用obj.operator()(i);
	//int result1 = obj.operator()(i); // 和上面的语句等价


	biggerthanzero1 obj1(5);//注意:这是对象定义并初始化,所以调用的是构造函数
	obj1(2); //这里已经初始化过了,调用的是对象obj的()圆括号。

	//只要这个对象所属的类重载了()“函数调用运算符”,那么这个类对象就变成了可调用的了,
	//而且可以调用多个版本的(),只要在参数类型或者数量上有差别即可,即重载。如下面:
	obj1(5, 6); //调用含有两个参数的对象obj的()圆括号

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



	//二: 不同调用对象的相同调用形式

	//函数echobvalue和类 biggerthanzero 的重载的(),这两个东西,调用参数和返回值相同,就叫做“调用形式相同”
	//一种调用形式 对应 一个函数类型: int(int);
	// 函数类型:int(int) //表示接受一个int参数,返回一个int值

	//引入概念叫 “可调用对象”,如下两个都是可调用对象。
	//a) echobvalue函数。
	//b) 重载了函数调用运算符的biggerthanzero类对象。


	//把这些可调用对象的指针保存起来,目的是方便我们随时调用这些“可调用对象”,这些指针类似
	//C语言中的函数指针。

	//那么我们可以用map 这种键值对数据类型,键存放“标识”,值存放“函数指针”,如下:
	//"add", 0x123
	//"red", 0x456

	map<string, int(*)(int) > myoper;
	myoper.insert({ "ev", echobvalue }); //用insert方法往这个容器中增加了一项,键值对。

	biggerthanzero obj2;
	//myoper.insert({ "bt", biggerthanzero });  
	//myoper.insert({ "ev", obj2 });
	//上面两种方式都不可以,标准库引入一个新的概念"function" 解决这个问题 


	//三、标准库function类型介绍
	//function 类模板,要提供模板参数来表示该function类型能够表示的“对象的调用形式”。
	//function<int(int)> //这就叫  声明了一个function()类型,用来代表一个可调用对象,它所代表的这个可调用对象是:
		//接受一个int参数,返回的也是一个int类型,

	function<int(int)> f1 = echobvalue; //函数指针
	function<int(int)> f2 = obj2; //类对象,因为类中有()重载
	function<int(int)> f3 = biggerthanzero(); //用类名生成一个对象,也可以,因为类中有()重载。

	//调用
	f1(5);// 5
	cout << f2(3) << endl; //3
	cout << f3(-5) << endl; //0

	//下面就可以在map中存放function类型 从而解决上面的 存储调用函数指针问题
	map<string, function<int(int)>> myoper1 = {
		{ "ev", echobvalue },
		{ "bt", obj2 },
		{ "bt2", biggerthanzero() }
	};

	myoper1["ev"](12); //就是调用echobvalue 函数  输出:12 
	cout << myoper1["bt"](3) << endl; //调用obj对象的()操作符  输出:3 
	cout << myoper1["bt2"](-5) << endl; //调用biggerthanzero类对象的()操作符  输出:0


	//function<int(int)> f1 = echobvalue1;//注意 如果echobvalue 函数重载了,就无法放到function<>类型的对象中, function不能识别到底使用哪个echobvalue函数,会提示错误
	//上面的问题,我们可以通过定义函数指针来解决
	int(*fp1)(int) = echobvalue1; //定义函数指针,在重载情况下,不会产生二义性,因为函数指针里有对应的参数类型和返回类型。
	int(*fp2)() = echobvalue1;
	int(*fp3)(int) = echobvalue1;

	function<int(int)> ff1 = fp1; //直接赋函数指针,而不是函数名echobvalue1
	function<int()> ff2 = fp2;
	function<int(int)> ff3 = fp3;

	ff1(3);
	cout << ff2() << endl;
	ff3(3);

	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值