C++ Primer 5th笔记(chap 14 重载运算和类型转换)可调用对象与function
1. 5种形式
可调用对象有5种形式,类型各不同:
形式 | 解释 |
---|---|
函数 | 返回值类型和实参类型 |
函数指针 | 返回值类型和实参类型 |
lambda表达式 | 类类型 |
bind创建的对象 | todo |
重载了函数调用运算符的类 | 类类型 |
2. 虽然可调用对象类型不同,但是调用形式可以一样
调用形式指明了调用返回的类型以及传递给调用的实参类型。不同的可调用对象可能具有相同的调用形式。
eg. 类型都为int(int, int)
// ordinary function
int add(int i, int j) { return i + j; }//lambda表达式,其产生一个未命名的函数对象类
auto mod = [](int i, int j) { return i % j; };// function-object class
struct divide
{int operator()(int denominator, int divisor){return denominator / divisor;}
};//调用代码
//使用map映射
map<string,function<int(int,int)> > binops;
binops.insert({"+", add});
//error,不能将mode或divide insert到binope中,因为他们类型不是函数指针
binops.insert({"%", mod});
有个问题:不能统一调用
3. 如何统一调用?
标准库function类型:标准库function类型是一个模板,定义在头文件functional中,用来表示对象的调用形式。
使用时需要创建一个具体的function类型。(必须提供其所表示的对象的调用形式)
操作 | 解释 |
---|---|
function f; | f是一个用来存储可调用对象的空function,这些可调用对象的调用形式应该与类型T相同。 |
function f(nullptr); | 显式地构造一个空function |
function f(obj) | 在f中存储可调用对象obj的副本 |
f | 将f作为条件:当f含有一个可调用对象时为真;否则为假。 |
定义为function的成员的类型f(args) | 调用f中的对象,参数是args |
result_type | 该function类型的可调用对象返回的类型 |
argument_type | 当T有一个或两个实参时定义的类型。 |
first_argument_type | 第一个实参的类型 |
second_argument_type | 第二个实参的类型 |
eg. function<int(int, int)>
function<int(int,int)> f1=add; //函数指针
function<int(int,int)> f2=divide(); //函数对象类的指针
function<int(int,int)> f3=[](int i,int l){return i*j;}; //lambdacout << f1(4,2) << endl; // prints 6
cout << f2(4,2) << endl; // prints 2
cout << f3(4,2) << endl; // prints 8
eg2.
//使用map映射
map<string,function<int(int,int)> > binops={{"+",add}, //函数指针{"-",std::minus<int>()}, //标准库函数对象{"/",divide()}, // 用户定义的函数对象{"*",[](int i,int j){return i*j;}}, //未命名的lambda{"%",mod} //已命名的lambda对象
};//这个时候insert是可以的
binops.insert( {"+", add} ); //函数指针
binops.insert( {"/",divide()} ); //函数对象
binops.insert( {"%", mod} ); //lambda表达式
binops.insert({"+"},[](int a,in b){return add(a,b);});//lambda表达式
binops.insert({ "add" , [](int a, int b) {return add(a, b); } });//lambda表达式cout << binops["+"](10, 5)<<endl;//调用add(10, 5)
cout << binops["-"](10, 5) << endl;
cout << binops["/"](10, 5) << endl; //使用divide对象调用括号运算符
cout << binops["*"](10, 5) << endl;
cout << binops["%"](10, 5) << endl;//调用lambda函数对象
cout << binops["add"](10, 5) << endl;//调用lambda函数对象
3.1 不能直接将重载函数的名字存入 function 类型的对象中,这样做会产生二义性错误。
int add(int i,int j){return i + j;}
Sales_data add(const Sales_data&,const Sales_data&);
map<string,funciton<int(int,int)>> binops;
binops.insert({"+",add}); //错误,不能区分是哪个add
3.2 解决方法
存储函数指针而非函数名字:
int (*fp) (int,int) = add;
binops.insert("add",fp); //正确,fp指向正确的add版本
- C++11新标准库中的function类与旧版本中的unary_function和binary_function没有关系,后两个类已经被bind函数代替。
【引用】
[1] 代码functionObject.h
C++ Primer 5th笔记(chap 14 重载运算和类型转换)可调用对象与function相关推荐
- C++ Primer 5th笔记(chap 14 重载运算和类型转换)二义性类型转换
1. 在两种情况下会产生二义性转换歧义: 1.1 A类定义了一个接受B类对象的转换构造函数,同时B类定义了一个转换目标是A类的类型转换运算符. struct B; struct A {A() = de ...
- C++ Primer 5th笔记(chap 14 重载运算和类型转换)函数调用运算符
1. 定义 如果类定义了调用运算符(重载了函数调用运算符),则该类的对象被称作函数对象(function object),可以像使用函数一样使用该类的对象, eg. struct absInt{int ...
- C++ Primer 5th笔记(chap 14 重载运算和类型转换)递增和递减运算符
并不要求递增和递减运算符一定是类的成员函数,但是因为这个运算符改变的正好是所操作的对象的状态,所以建议将它们设为成员函数. 为了和内置版本保持一致,前置运算符应该返回递增或递减后对象的引用. 为了和内 ...
- C++ Primer 5th笔记(chap 14 重载运算和类型转换)重载运算概述
1. 定义 重载运算是具有特殊名字的函数,它们的名字由关键字operator和其后要定义的运算符号组成. 2. 运算符表 2.1 可重载运算符 运算符类型 运算符种类 双目算术运算符 + (加),-( ...
- C++ Primer 5th笔记(chap 14 重载运算和类型转换)函数匹配与重载运算符
如果一个类既提供了转换目标是算术类型的类型转换,也提供了重载的运算符,则将会遇到重载运算符与内置运算符的二义性问题. 如果a是一种类型,表达式 a sym b 可能是: //不能通过调用形式来区分当前 ...
- C++ Primer 5th笔记(chap 14 重载运算和类型转换)lambda函数对象
1. 定义 lambda是函数对象:编写一个lambda后,编译器会将该表达式转换成一个未命名类的未命名对象,类中含有一个重载的函数调用运算符. eg. stable_sort(words.begin ...
- C++ Primer 5th笔记(chap 14 重载运算和类型转换)成员运算符
成员运算符分为两种: 解引用运算符* 箭头运算符-> 设计准则 箭头运算符必须是类的成员. 解引用运算符通常也是类的成员,尽管并非必须如此. 重载的箭头运算符必须返回类的指针或者自定义了箭头运算 ...
- C++ Primer 5th笔记(chap 14 重载运算和类型转换)算术和关系运算符
运算符 双目算术运算符 + (加),-(减),*(乘),/(除),% (取模) 关系运算符 ==(等于),!= (不等于),< (小于),> (大于>,<=(小于等于),> ...
- C++ Primer 5th笔记(chap 14 重载运算和类型转换)类类型转换
1. 定义 类型转换运算符:(既然一个类类型可以由实参类型对象隐式转换而来,那么)一个类类型的值也可以转换成其它类型 形式 : operator type() const type 表示某种类型,类型 ...
最新文章
- Python核心编程笔记---- print
- 学Java还是Python?一张图告诉你!
- iOS 9音频应用播放音频之音量设置与声道设置
- 统计元音(格式控制)
- 危害网络安全或入信用“黑名单”
- php后台富文本编辑器的内容调用到前端小程序页面的一些显示问题,如:nbsp;
- 基于Nexys4DDR的数字时钟设计
- (六)将样式转换模型从TensorFlow转换为TensorFlow Lite
- PoolTogether 奖池开奖一名用户赢得 43,760 美元,本金仅为 73 美元
- linux发布成服务,linux服务简单部署
- 三元组顺序表表示的稀疏矩阵加法_知识表示学习记录(1)
- 增长战略五大维度:单点突破、由内而外、锚点绑定、群体延伸、圈层建设
- 【计算机体系结构实验】指令调度和延迟分支
- Win10 / 11新电脑最简单跳过联网激活和使用本地账户登录方法
- 8000 sentences of oral English(four)
- Danar程序员之家在CSDN安家落户啦
- C语言程序设计实践题,2020年C语言程序设计实践实验题目.doc
- 苹果AppStore应用商店生存之道:国内iOS开发者创业经验分享(三)
- centos7安装配置yum软件仓库
- 虚拟机架设传奇3服务器,WIN8安装虚拟机玩传奇3教程-转
热门文章
- 第十一届青少年蓝桥杯国赛真题精选 - 编程题
- Python 实现简单的石头剪刀布小游戏
- jQuery-基本选择器的种类
- java基础求三角形的面积
- Java 洛谷 P1307 数字反转
- 中南大学计算机085403,What?这些个专业改考数一英一了!
- AI公开课:19.04.10颜水成—360副总裁《人工智能:观察与实践》课堂笔记以及个人感悟—191017再次更新
- ML之LoRBaggingRF:依次利用Bagging、RF算法对泰坦尼克号数据集 (Kaggle经典案例)获救人员进行二分类预测——模型融合
- JAVA_OA(bug篇)(一):SpringMVC的bug1
- 《疯狂JAVA讲义》笔记1