C++可调用对象与函数表
c++的可调用对象 有
- 函数
- 函数指针
- lambda表达式
- bind的对象
- 重载了函数调用运算符的类
如何调用?
函数调用
void afuncToCall()
{
cout << "call me"<<"\n";
}
//1.call function
afuncToCall();
函数指针调用
void func(int i){
cout << "a function called by function pointer i= "<<i<<"\n";
}
//声明一个函数指针
void(*f)(int i);
//对函数指针赋值
f=func;
//调用指针函数
f(5);
或者使用typedef缩写函数指针
//function pointer
typedef void(*AbleCallFuncP)(int i) ;
//2.function pointer
AbleCallFuncP callFuncPointer= func;
callFuncPointer(5);
lambda表达式调用
auto flambda = [](int i){
cout << "lambda i is " << i << "\n";
};
flambda(7);
bind的对象
#include <functional>
void func(int i){
cout << "a function called by bind object i= "<<i<<"\n";
}
auto fbind = bind(func,std::placeholders::_1);
fbind(9);
重载了函数调用运算符的类
struct callableStruct
{
int operator()(int val){
return (val<0)?-val:val;
}
};
// callableStruct callableSut;
int i = callableSut(-2);
函数表
现在,我们拥有了5种函数调用方式,那么,在一个项目里,我们很可能希望使用一个统一的函数表来管理这些函数调用对象,以上面的函数为例,我们其实拥有了5个参数为int类型的调用对象,使用map可以方便地实现函数表;
只是,问题在于,这5种可调用对象的类型是不同的,我们无法将他们使用同一种类型放入map的second字段中,于是万能的C++标准大神们发明了function类模板来解决这个问题。
罗列5种可调对象如下:
//function
void afuncToCall(int i)
{
cout << "call me a plain functon i is "<<i <<"\n";
}
//function pointer
typedef void(*AbleCallFuncP)(int i) ;
//called by function pointer
void func1(int i){
cout << "a function called by function pointer i= "<<i<<"\n";
}
//called by bind
void func2(int i){
cout << "a function called by bind i= "<<i<<"\n";
}
//callable class
struct callableStruct
{
void operator()(int i){
cout << "a function called by callableStruct i= "<<i<<"\n";
}
};
//1.call function
//afuncToCall();
// //2.function pointer
AbleCallFuncP callFuncPointer= func1;
//3.lambda
auto flambda = [](int i){
cout << "lambda i is " << i << "\n";
};
//4 bind
auto fbind = bind(func2,std::placeholders::_1);
//5.operator ()
callableStruct callableSut;
让我们用function统一它们的类型
#include <functional>
#include <map>
#include <string>
// using std::map;
void TestCallableObj()
{
typedef function<void(int)> FuncVI;
typedef map<string,FuncVI> FuncAbleObjMap;
FuncAbleObjMap callableObjMap;
callableObjMap.insert(FuncAbleObjMap::value_type(string("plain function call"),afuncToCall));
callableObjMap.insert(FuncAbleObjMap::value_type(string("function pointer call"),callFuncPointer));
callableObjMap.insert(FuncAbleObjMap::value_type(string("lambda call"),flambda));
callableObjMap.insert(FuncAbleObjMap::value_type(string("bind call"),fbind));
callableObjMap.insert(FuncAbleObjMap::value_type(string("operator() call"),callableStruct()));
callableObjMap["plain function call"](1);
callableObjMap["function pointer call"](2);
callableObjMap["lambda call"](3);
callableObjMap["bind call"](4);
callableObjMap["operator() call"](5);
}
输出结果
call me a plain functon i is 1
a function called by function pointer i= 2
lambda i is 3
a function called by bind i= 4
a function called by callableStruct i= 5
由此可见,通过function模板,我们将类型本不同的5个可调用对象打包成统一的类型,因为它们的返回值和参数类型是完全一样的。通过函数表的使用,我们可以写出封装更好的调用函数。
如果觉得这样的调用太繁琐,可以使用宏来缩写下
比如:
#define CALL1(x) callableObjMap[#x](1);
CALL1(plain function call);
CALL1(bind call);
备注,本文没有涉及到函数成员函数 和静态成员函数的调用,权当归类到函数一类了。但是其调用细节和函数还是有差异的。
C++可调用对象与函数表的更多相关文章
- C++ 关于类与对象在虚函数表上唯一性问题 浅析
[摘要] 非常多教材上都有介绍到虚指针.虚函数与虚函数表.有的说类对象共享一个虚函数表,有的说,一个类对象拥有一个虚函数表.还有的说,不管用户声明了多少个类对象,可是,这个VTABLE虚函数表仅仅有一 ...
- C++对象内存模型2 (虚函数,虚指针,虚函数表)
从例子入手,考察如下带有虚函数的类的对象内存模型: class A { public: virtual void vfunc1(); virtual void vfunc2(); void func1 ...
- 深入理解类成员函数的调用规则(理解成员函数的内存为什么不会反映在sizeof运算符上、类的静态绑定与动态绑定、虚函数表)
本文转载自:http://blog.51cto.com/9291927/2148695 总结: 一.成员函数的内存为什么不会反映在sizeof运算符上? 成员函数可以被看作是类 ...
- C++对象的内存布局以及虚函数表和虚基表
C++对象的内存布局以及虚函数表和虚基表 本文为整理文章, 参考: http://blog.csdn.net/haoel/article/details/3081328 http://blog.csd ...
- C++虚函数表解析(图文并茂,非常清楚)( 任何妄图使用父类指针想调用子类中的未覆盖父类的成员函数的行为都会被编译器视为非法)good
C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛型技术 ...
- C++虚函数表和对象存储
C++虚函数表和对象存储 C++中的虚函数实现了多态的机制,也就是用父类型指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数,这种技术可以让父类的指针有"多种形态",这 ...
- C++对象内存模型2 (虚函数,虚指针,虚函数表)(转)
class A { public: virtual void vfunc1(); virtual void vfunc2(); void func1(); void func2(); virtual ...
- C++对象内存分布详解(包括字节对齐和虚函数表)
转自:https://www.jb51.net/article/101122.htm 1.C++对象的内存分布和虚函数表: C++对象的内存分布和虚函数表注意,对象中保存的是虚函数表指针,而不是虚函数 ...
- C++对象的内存分布和虚函数表
c++中一个类中无非有四种成员:静态数据成员和非静态数据成员,静态函数和非静态函数. 1.非静态数据成员被放在每一个对象体内作为对象专有的数据成员. 2.静态数据成员被提取出来放在程序的静态数据 ...
随机推荐
- 特定于类的内存管理---《C++必知必会》 条款36
我们可以量身定制 operator new 和 operator delete 用于某个类类型,而不是必须使用标准版的 operator new 和 operator delete. 注意:我们不可以 ...
- samba创建权限(复制)
1.今天发现用samba挂载开发过程中,发现别人的权限和我的经常不一致,导致提交git的时候都被提交了,心想应该有哪里有一个统一设置的可以设置用户的默认权限,后来百度之后找到下面的文章,以后创建文件和 ...
- Django RF:学习笔记(8)——快速开始
Django RF:学习笔记(8)——快速开始 安装配置 1.使用Pip安装Django REST Framework: pip install djangorestframework 2.在Sett ...
- 文件下载—SSH框架文件下载
1.准备下载的api组件 <dependency> <groupId>commons-io</groupId> <artifactId>commons- ...
- js动态创建Form表单并提交
javascript动态创建Form表单和表单项,然后提交表单请求,最后删除表单,代码片段如下(Firefox测试通过): var dlform = document.createElement('f ...
- Python3.x:免费代理ip的批量获取并入库
Python3.x:免费代理ip的批量获取并入库 一.简介 网络爬虫的世界,向来都是一场精彩的攻防战.现在许多网站的反爬虫机制在不断的完善,其中最令人头疼的,莫过于直接封锁你的ip.但是道高一尺魔高一 ...
- 利用ansible进行自动化构建etcd集群
上一篇进行了手动安装etcd集群,此篇利用自动化工具ansible为三个节点构建etcd集群 环境: master:192.168.101.14,node1:192.168.101.15,node2: ...
- IAsyncResult接口
#region 程序集 mscorlib.dll, v4.0.0.0 // C:\Program Files (x86)\Reference Assemblies\Microsoft\Framewor ...
- Redis之字符串
Redis 字符串 String 是redis最基本的类型,value 不仅可以是 String,也可以是数字. 使用 Strings 类型,可以完全实现目前 Memcached 的功能,并且效率更高 ...
- [SpringBoot] - 了解什么是SpringBoot,使用SpringBoot的配置文件
首先明白Spring是什么,Spring是Java开发的一个框架,为了方便简化Java开发. 什么是注解(注解式开发)? Spring的常用注解有哪些? 假如用SpringBoot构建一个网站程序,应 ...