持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情
函数调用运算符
- ()圆括号是函数调用的明显标记, ()也叫函数调用运算符;
- 如果在类中重载了函数调用运算符,就可以想使用函数一样使用该类的对象了;
- 只要对象所属的类重载了 ()函数调用运算符,那么这个类对象就变成了可调用的;
函数对象
1、调用类的成员函数,函数名为operator()(参数)
写法apple.operator()(参数);
可以简写为apple(参数)
此时apple(参数)这个使用方法,和一个真正的函数调用的写法是一样的,比如fun(参数)
所以称呼apple为一个函数对象,类A就是一个函数对象类
#include <iostream>
using namespace std;
class A{
public:
int i = 8;
void operator()(int value){
cout<<"类的operator()函数被调用"<<endl;
cout<<"value+100="<<value+100<<endl;
}
};
void fun(int value){
cout<<"fun函数被调用"<<endl;
cout<<"value+100="<<value+100<<endl;
}
int main(){
A apple;
apple(9);
fun(9);
apple.operator()(9);
return 0;
}
/*
类的operator()函数被调用
value+100=109
fun函数被调用
value+100=109
类的operator()函数被调用
value+100=109
*/
和有参构造的区别
如果前面有类名,说明要调用有参构造
如果前面没有类名,说明要调用重载小括号函数
#include <iostream>
using namespace std;
class A{
public:
int i = 8;
void operator()(int value){
cout<<"类的operator()函数被调用"<<endl;
cout<<"value+100="<<value+100<<endl;
}
A(int value){
cout<<"类的有参构造被调用"<<endl;
i = value;
}
};
void fun(int value){
cout<<"fun函数被调用"<<endl;
cout<<"value+100="<<value+100<<endl;
}
int main(){
A apple(55);
apple(1);
fun(2);
apple.operator()(3);
return 0;
}
/*
类的有参构造被调用
类的operator()函数被调用
value+100=101
fun函数被调用
value+100=102
类的operator()函数被调用
value+100=103
*/
小结
如果这个对象所属的类重载了"()",那么这个类对象就变成了可调用对象(函数对象),而且可以调用多个版本的"()",只要在参数类型或者数量上有差别就行。
函数类型
函数类型就是函数的返回值和参数类型的组合
int(int)
int(double)
用函数指针来调用可调用对象
可调用对象有:函数,函数指针,lambda表达式,bind创建的对象,以及重载了函数调用符的类。
int (*p1) (int value);
p1 = A::operator();
p1 = operator();
A a;
p1 = a.operator();//以上都不行
void fun(int value){
cout<<"fun函数被调用"<<endl;
cout<<"value+100="<<value+100<<endl;
}
void (*p1) (int value);
p1 = fun;//可以
p1(100);
都会报错,指向绑定函数的指针只能用于调用函数,不能用于调用函数对象
解决方法,function类模板
function类模板
function是一个通用的多态函数包装器。 std :: function的实例可以存储,复制和调用任何可调用的目标 :包括函数,lambda表达式,绑定表达式或其他函数对象,以及指向成员函数和指向数据成员的指针
需要头文件#include
#include <iostream>
#include <functional>
using namespace std;
class A{
public:
int i = 8;
void operator()(int value){
cout<<"类的operator()函数被调用"<<endl;
cout<<"value+100="<<value+100<<endl;
}
};
void fun(int value){
cout<<"fun函数被调用"<<endl;
cout<<"value+100="<<value+100<<endl;
}
int main(){
function<void(int)> func1 = A();
A apple;
function<void(int)> func2 = apple;
function<void(int)> func3 = fun;
func1(100);
func2(200);
func3(300);
return 0;
}
/*
类的operator()函数被调用
value+100=200
类的operator()函数被调用
value+100=300
fun函数被调用
value+100=400
*/
通过map调用
#include <iostream>
#include <functional>
#include <map>
using namespace std;
class A{
public:
int i = 8;
void operator()(int value){
cout<<"类的operator()函数被调用"<<endl;
cout<<"value+100="<<value+100<<endl;
}
};
void fun(int value){
cout<<"fun函数被调用"<<endl;
cout<<"value+100="<<value+100<<endl;
}
int main(){
function<void(int)> func1 = A();
A apple;
function<void(int)> func2 = apple;
function<void(int)> func3 = fun;
map<string,function<void(int)>> mymap;
mymap.insert({"callbyA",func1});
mymap.insert({"callbyApple",func2});
mymap.insert({"callbyfunc",func3});
cout<<"---通过容器mymap调用---"<<endl;
mymap["callbyA"](7);
mymap["callbyApple"](8);
mymap["callbyfunc"](9);
return 0;
}
/*
---通过容器mymap调用---
类的operator()函数被调用
value+100=107
类的operator()函数被调用
value+100=108
fun函数被调用
value+100=109
*/
typedef定义函数指针类型的写法
#include <iostream>
#include <functional>
#include <map>
using namespace std;
class A{
public:
int i = 8;
void operator()(int value){
cout<<"类的operator()函数被调用"<<endl;
cout<<"value+100="<<value+100<<endl;
}
};
void fun(int value){
cout<<"fun函数被调用"<<endl;
cout<<"value+100="<<value+100<<endl;
}
int main(){
map<string,void (*) (int)> v1;
void (*p3) (int);
p3 = fun;
v1.insert({"func1",p3});
v1["func1"](55);
cout<<"----typedef----"<<endl;
typedef void (*Func) (int);
Func p4 = fun;
map<string,Func> v2;
v2.insert({"func1",p4});
v2["func1"](55);
return 0;
}
/*
fun函数被调用
value+100=155
----typedef----
fun函数被调用
value+100=155
*/
由此可见当要创建多个函数指针的时候,建议用typedef。
值得注意的是
map<string,void (*) (int)> v1;
括号中*没带参数,和string不带参数一样的道理