
C++标准库:可调用对象与 function
标准库
重载函数 与
发布日期:2021-05-07 06:34:58
浏览次数:21
分类:精选文章
本文共 2467 字,大约阅读时间需要 8 分钟。
本文为《C++ Primer》的读书笔记
目录
可调用对象与调用形式
- C++ 中有几种可调用的对象: 函数、函数指针、lambda 表达式、
bind
创建的对象以及重载了函数调用运算符的类 - 和其他对象一样, 可调用的对象也有类型。例如, 每个 lambda 有它自己唯一的(未命名)类类型; 函数及函数指针的类型则由其返回值类型和实参类型决定, 等等
不同类型可能具有相同的调用形式
- 然而, 两个不同类型的可调用对象却可能共享同一种 调用形式(callsignature)。调用形式指明了调用返回的类型以及传递给调用的实参类型。一种调用形式对应一·个函数类型, 例如:
int(int, int)
- 对于几个可调用对象共享同一种调用形式的情况,有时我们会希望把它们看成具有相同的类型。例如:
// 普通函数int add(int i, int j) { return i + j; }// lambda, 其产生一个未命名的函数对象类auto mod = [](int i, int j) { return i % j; };// 函数对象类struct divide { int operator() (int denominator, int divisor) { return denorninator / divisor; };};
- 上面这些可调用对象尽管它们的类型各不相同, 但是共享同一种调用形式:
int (int, int)
- 我们可能希望使用这些可调用对象构建一个简单的桌面计算器。为了实现这一目的,需要定义一个函数表 (function table) 用于存储指向这些可调用对象的 “指针”。当程序需要执行某个特定的操作时, 从表中查找该调用的函数
- 函数表很容易通过
map
来实现。对于此例来说, 我们使用一个表示运算符符号的string
对象作为关键字;使用实现运算符的函数作为值 - 假定我们的所有函数都相互独立, 并且只处理关于
int
的二元运算, 则map
可以定义成如下的形式:
// 构建从运算符到函数指针的映射关系, 其中函数接受两个 int、返回一个 intmapbinops;// 将 `add` 的指针添加到 `binops` 中binops.insert({ "+", add});
- 但是我们不能将
mod
或者divide
存入binops
。问题在于mod
是个 lambda 表达式, 而每个 lambda 有它自己的类类型, 该类型与存储在binops
中的值的类型不匹配
标准库 function
模板类
#include
- 下面的
function
类型表示接受两个int
、返回一个int
的可调用对象。甚至只要可调用对象的参数和返回类型能够隐式转化为int
即可
function
functionf1 = add; // 函数指针function f2 = divide(); // 函数对象类的对象function f3 = [] (int i, int j) // lambda { return i * j; };cout << f1(4,2) << endl; cout << f2(4,2) << endl;cout << f3(4,2) << endl;
- 使用这个
function
类型我们可以重新定义map
:
map> binops = { { "+", add}, // 函数指针 { "-", std::minus ()}, // 标准库函数对象 { "I", divide()}, // 用户定义的函数对象 { "*", [](int i, int j) { return i * j; }}, // 未命名的lambda { "%", mod}}; // 命名了的 lambda 对象};
binops["+"](10, 5); //调用 add(10, 5)binops["-"](10, 5); //使用 minus 对象的调用运算符binops["/"](10, 5); //使用 divide 对象的调用运算符binops["*"](10, 5); //调用 lambda 函数对象binops["%"](10, 5); //调用 lambda 函数对象int a, b;string op;cin >> a >> op >> b;cout << binops[op](a, b) << endl;
重载函数 与 function
- 我们不能(直接)将重载函数的名字存入
function
类型的对象中:
int add(int i, int j) { return i + j; }Sales_data add(const Sales_data&, const Sales_data&);map> binops;binops.insert( { "+", add} ); //错误: 哪个add?
- 解决上述二义性问题的一条途径是存储函数指针而非函数的名字:
int (*fp)(int, int) = add; // 指针所指的 add 是接受两个int 的版本binops.insert({ "+", fp}); // 正确: fp 指向一个正确的 add 版本
- 同样, 我们也能使用 lambda 来消除二义性:
// 正确:使用lambda 未指定我们希望使用的add版本binops.insert({ "+", [] (int a, int b) { return add(a, b);} });
发表评论
最新留言
留言是一种美德,欢迎回访!
[***.207.175.100]2025年04月15日 07时50分21秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Hmz 的女装(递推)
2021-05-09
HDU5589:Tree(莫队+01字典树)
2021-05-09
不停机替换线上代码? 你没听错,Arthas它能做到
2021-05-09
sharding-jdbc 分库分表的 4种分片策略,还蛮简单的
2021-05-09
分库分表的 9种分布式主键ID 生成方案,挺全乎的
2021-05-09
MySQL不会丢失数据的秘密,就藏在它的 7种日志里
2021-05-09
Python开发之序列化与反序列化:pickle、json模块使用详解
2021-05-09
回顾-生成 vs 判别模型-和图
2021-05-09
采坑 - 字符串的 "" 与 pd.isnull()
2021-05-09
无序列表 - 链表
2021-05-09
SQL 查询强化 - 数据准备
2021-05-09
SQL 强化练习 (四)
2021-05-09
Excel 拼接为 SQL 并打包 exe
2021-05-09
Pandas数据分析从放弃到入门
2021-05-09
Matplotlib绘制漫威英雄战力图,带你飞起来!
2021-05-09
机器学习是什么
2021-05-09
《小王子》里一些后知后觉的道理
2021-05-09
《自私的基因》总结
2021-05-09
《山海经》总结
2021-05-09