115 C++ 函数调用运算符 - (实际上就是小括号),function类模版,函数对象,仿函数,可调用对象 概念。通过function存储可调用对象的指针。

一 函数调用运算符 (实际上就是小括号)

我们写一个函数调用,更加直观的理解这个意思

int funcadd(int a, int b) {
	return a + b;
}
void funcvoid() {
	cout << "funcvoid call" << endl;
}

void main() {
	funcadd(1, 2);
	funcvoid();
	//从上面可以看到,我们调用funcadd函数和funcvoid函数的方法都是给这个函数名后面加上()
	//	即使这个funcvoid这个函数不需要任何参数,也是要加上()。
	//这里就有一个概念,需要我们记住了,圆括号就是函数调用的明显标记
	//	()有个称呼,叫做“函数调用运算符”

}

从上面可以看到,我们调用funcadd函数和funcvoid函数的方法都是给这个函数名后面加上()
    //    即使这个funcvoid这个函数不需要任何参数,也是要加上()。
    //这里就有一个概念,需要我们记住了,圆括号就是函数调用的明显标记
    //    ()有个称呼,叫做“函数调用运算符”

二 函数对象/ 仿函数

如果我们在类中重载了 “函数调用运算符”,那么我们就可以像函数一样的使用该类的对象了

一旦该类重载了(),那么该类的对象多了个新名字 “函数对象”

class Teacher9 {
public:
	int operator()(int a,int b ) {
		return a + b;
	}
	int operator()(int a) {
		return a + 10;
	}
	bool operator()(int a,double b) {
		return a > b;
	}

	int operator()() {
		cout << "operator()()" << endl;
		return 100;
	}

	Teacher9() {
		cout << "Teacher9 构造函数被调用"<<endl;
	}

};
void main() {
	Teacher9 tea;
	auto a= tea(2,3);
	int b = tea(2);
	bool c = tea(2, 1.1);
	cout << a << endl;//5
	cout << b << endl;//12
	cout << c << endl;//1
	Teacher9();//这是构造一个临时对象
	Teacher9()();//这是构造一个临时对象,然后调用这个临时对象的operator() () 无参数的operator()

	cout << "duandian" << endl;
}

三。概念:调用形式相同。

还是以例子解释:

如下的例子中,由于 changestrtoint方法的参数/返回值 和 Teacher10中重载的operator()(string)的参数/返回值相同。

如果两个函数参数一样,返回值一样这两函数就有了联系,联系是:调用形式相同。

class Teacher10 {
public:
	int operator()(string str) {
		int  x = stoi(str); //stoi 遇到字符会停下来,需要 #include<string> 
		return x;
	}
};

int changestrtoint(string str) {
	return 1;
}

四。概念:可调用对象。

如下两个都是可调用对象

changestrtoint 函数 (一般函数)

重载了 函数调用运算符 的类对象 

我们现在有个需求,就是将这些可调用对象的指针存储起来,方便以后随时调用,应该怎么弄额?

这里我们首先想到了 函数指针。

但是对于 函数对象,好像都记录不了,那更没办法存储在vector或者list,或者map中了

void main() {
	typedef int(*ptype)(string str);

	ptype s1 = changestrtoint;

	Teacher10 tea;

	//ptype s4 = tea;//build error
	//ptype s2  = &(Teacher10::operator()); build error
	//ptype s3  = Teacher10::operator(); build error
}

我们这里用map储存,但是还是有个问题解决不了,就是怎么存储这个 Teacher 函数对象的实例tea呢?

存储在map中,key存储成int或者string 什么的都可以,只要不重复就行

关键是这个value,需要是  可调用对象的指针。这样表示类型   int(*)(string)

map<int , int(*)(string)>

void main() {
	typedef int(*ptype)(string str);

	ptype s1 = changestrtoint;

	Teacher10 tea;
	//ptype s4 = tea;//build error
	//ptype s2  = &(Teacher10::operator()); build error
	//ptype s3  = Teacher10::operator(); build error

	map<int, int(*)(string)> myopr;
	myopr.insert(make_pair(1, changestrtoint));
	//myopr.insert(make_pair(2, tea));//build error
	//因此问题,我们要学习function类模版
}

五。function 类模版介绍:

#include <functional>

function类模版:要提供模版参数来表示该function类型能够表示的“对象的调用形式”。

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

void main() {

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

	function<int(string)> f1 = changestrtoint;
	Teacher10 tea;
	function<int(string)> f2 = tea;
	//调用一下,结果都是OK的
	auto aa = f1("87ui");
	cout << aa << endl;

	auto bb = f2("87ui");
	cout << bb << endl;

	map<int, function<int(string)>> myopr;
	myopr.insert(make_pair(1,f1));
	myopr.insert(make_pair(2, f2));

	map<int, function<int(string)>>::iterator it= myopr.find(2);
	cout << "(*it).first = " << (*it).first << endl;
	function<int(string)> zhizhen = (*it).second;
	int res = zhizhen("90k");
	cout << res << endl;
}

结果

1
87
(*it).first = 2
90

如果changestrtoint有重载,就无法放入到function里

class Teacher10 {
public:
	int operator()(string str) {
		int  x = stoi(str); //stoi 遇到字符会停下来,需要 #include<string> 
		return x;
	}
};

int changestrtoint(string str) {
	return 1;
}

int changestrtoint( ) {
	return 2;
}

//如果changestrtoint有重载,就无法放入到function里
void main() {

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

	function<int(string)> f1 = changestrtoint;//这一行build error
	Teacher10 tea;
	function<int(string)> f2 = tea;
	//调用一下,结果都是OK的
	auto aa = f1("87ui");
	cout << aa << endl;

	auto bb = f2("87ui");
	cout << bb << endl;

	map<int, function<int(string)>> myopr;
	myopr.insert(make_pair(1,f1));
	myopr.insert(make_pair(2, f2));

	map<int, function<int(string)>>::iterator it= myopr.find(2);
	cout << "(*it).first = " << (*it).first << endl;
	function<int(string)> zhizhen = (*it).second;
	int res = zhizhen("90k");
	cout << res << endl;
}

如何解决:通过函数指针转一下就OK了

class Teacher10 {
public:
	int operator()(string str) {
		int  x = stoi(str); //stoi 遇到字符会停下来,需要 #include<string> 
		return x;
	}

	int operator()() {
		int  x = 199; 
		return x;
	}
};

int changestrtoint(string str) {
	return 1;
}

int changestrtoint( ) {
	return 2;
}

//如果changestrtoint有重载,就无法放入到function里
void main() {

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

	//fix 方案
	int(*p)(string) = changestrtoint;
	function<int(string)> f1 = p;
	Teacher10 tea;
	function<int(string)> f2 = tea;
	//调用一下,结果都是OK的
	auto aa = f1("87ui");
	cout << aa << endl;

	auto bb = f2("87ui");
	cout << bb << endl;

	map<int, function<int(string)>> myopr;
	myopr.insert(make_pair(1,f1));
	myopr.insert(make_pair(2, f2));

	map<int, function<int(string)>>::iterator it= myopr.find(2);
	cout << "(*it).first = " << (*it).first << endl;
	function<int(string)> zhizhen = (*it).second;
	int res = zhizhen("90k");
	cout << res << endl;
}

如果函数对象有重载,则不影响

如下代码是可以正常运行的

class Teacher10 {
public:
	int operator()(string str) {
		int  x = stoi(str); //stoi 遇到字符会停下来,需要 #include<string> 
		return x;
	}

	int operator()() {
		int  x = 199; 
		return x;
	}
};

int changestrtoint(string str) {
	return 1;
}

//int changestrtoint( ) {
//	return 2;
//}

//如果changestrtoint有重载,就无法放入到function里
void main() {

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

	function<int(string)> f1 = changestrtoint;
	Teacher10 tea;
	function<int(string)> f2 = tea;
	//调用一下,结果都是OK的
	auto aa = f1("87ui");
	cout << aa << endl;

	auto bb = f2("87ui");
	cout << bb << endl;

	map<int, function<int(string)>> myopr;
	myopr.insert(make_pair(1,f1));
	myopr.insert(make_pair(2, f2));

	map<int, function<int(string)>>::iterator it= myopr.find(2);
	cout << "(*it).first = " << (*it).first << endl;
	function<int(string)> zhizhen = (*it).second;
	int res = zhizhen("90k");
	cout << res << endl;
}

  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值