C++中的可调用对象
在C++中,常常会利用函数来简化程序流程。函数的存在使得C++整体更加“模块化”,因而也使得代码可读性大大提高。
在C++程序中,常常会很灵活地调用函数来实现不同的功能与目的(函数重载、继承多态等等)。在一些情况下,可以传入类似函数一样的可调用对象,使得这一用法更加强大。
下面是简单整理的几种调用方法:
首先,给定一个共同的前提。标准库提供了排序算法来帮助设计者实现基础的排序,如果设计者希望更加灵活地按照自定义的排序方式来调用标准函数进行排序,就可以在标准排序函数中,传入一个指向自定义的可调用对象即可。
下面,就依照这个前提,实现对一组int元素的升序排序,这里使用std::vector<int>来进行装载,即目标是让这个vector中的元素按照升序重新排列。
1. 使用Lambda:
事实上,在C++中,Lambda表达式就可以理解成生成一个可调用函数,而且这个函数是inline的。当然,这里可以直接把它作为一个可调用对象来使用。

2. 通过函数名直接调用自定义函数:
通过传入一个自定义函数的名字(编译器会自动将其转换成函数指针类型),可以达到直接调用该自定义函数的目的。
首先,根据这个前提定义一个名为isLess的函数,就像这样:

然后,直接传入这个函数的名字(isLess)即可:

3. 传入指向自定义函数的函数指针:
类似于2,传入指向这个自定义函数的函数指针也可以调用这个可调用对象。
当然,首先定义一个指向这个函数的函数指针:

然后,就像调用函数一样,传入这个函数指针就可以了:

4. 使用标准库bind函数来生成一个可调用对象,进而对其调用:
std::bind函数可以根据一个已定义的函数,生成一个可调用对象,这个可调用对象的传入参数列表可以自己定义与设计。更炫酷的是,这个参数列表不一定非要和被绑定的函数参数列表一致!

5. 使用自定义的可调用对象:
或许这听起来有点儿意思,事实上的确如此。用户可自定义一个可调用对象,只需要重载这个对象的类的()符号。相信我,尽管C++的重载运算符算是比较复杂的操作,但其中乐趣无穷。
这里,简单地定义一个需要的类(当然,我们需要的重点是这个类一定要重载()符号,毕竟这才是调用对象的重头戏):

然后,在主调函数中,要实例化一个这个类的对象(所以才能称之为可调用“对象”嘛...),只需要简单地将这个对象看作是一个“可调用函数”就ok了!

6. 使用标准库定义的可调用对象:
既然说到了自定义可调用对象,那么标准库中很可能已经有相关的基本实现了。标准库提供了标准库中很多类型的基本操作的可调用对象,很多时候,对于简单的内置类型,需要相关操作时只需要简单地调用标准库提供的可调用对象即可。

以上就是简单地设计生成/调用可调用对象的几种方法,当然,有的时候不同的方法带来的效益可能不同,适时地使用相应的可调用对象可以极大地简化程序。
下面附上上述所有方案的代码,包含的头文件以及实现文件,需要自己来写。当然,都是一些简单的操作,看官自行写一写就好。
#include "modnar.h" #include "show.cpp"
#include "random.cpp" bool isLess(const int &a, const int &b) {
return a < b;
} class CompareObj {
public:
CompareObj() = default;
bool operator()(const int &a, const int &b) {
return a < b;
}
}; int main(int argc, char *argv[]) {
std::vector<int> vec();
bool (*pf)(const int &, const int &) = isLess;
// You can also get "pf" like this:
// decltype(isLess) *pf = isLess; // Method1. Use Lambda expression.
modnar::get_rand_seq(vec);
std::sort(vec.begin(), vec.end(),
[](const int &a, const int &b) { return a < b; });
modnar::show(vec); // Method2. Call a function by its name.
modnar::get_rand_seq(vec);
std::sort(vec.begin(), vec.end(), isLess);
modnar::show(vec); // Method3. Call a function by using a function pointer to it.
modnar::get_rand_seq(vec);
std::sort(vec.begin(), vec.end(), pf);
modnar::show(vec); // Method4. Use std::bind function to generate a callable object.
modnar::get_rand_seq(vec);
std::sort(vec.begin(), vec.end(),
std::bind(isLess, std::placeholders::_1, std::placeholders::_2));
modnar::show(vec); // Method5. Use a self-defined callable object.
CompareObj *comp = new CompareObj();
modnar::get_rand_seq(vec);
std::sort(vec.begin(), vec.end(), *comp);
modnar::show(vec); // Method6. Use the callable object provided by standard library.
modnar::get_rand_seq(vec);
std::sort(vec.begin(), vec.end(), std::less<int>());
modnar::show(vec); return ;
}
Main.cpp
若有相关内容的想法与方法,以及对文章的建议与异议,请评论区分享你的idea,提前说声谢谢。
@编辑于2019.3.8
C++中的可调用对象的更多相关文章
- ruby中的可调用对象--方法
上一篇讲了ruby中的可调用对象proc和lambda,他们都是块转换成的对象.ruby中的可调用对象还有方法.通过使用method方法,并且以方法名作为参数(字符串或者符号),就可以得到一个方法对象 ...
- ruby中的可调用对象--proc和lamdba
ruby中将块转变成对象的三种方法 ruby中的大部分东西都是对象,但是块不是.那么,如果你想存下来一个块,方便以后使用,你就需要一个对象.ruby中有三种方法,把块转换成可以利用的对象. Proc. ...
- Delphi 中的DLL 封装和调用对象技术(刘艺,有截图)
Delphi 中的DLL 封装和调用对象技术本文刊登2003 年10 月份出版的Dr.Dobb's 软件研发第3 期刘 艺摘 要DLL 是一种应用最为广泛的动态链接技术但是由于在DLL 中封装和调用对 ...
- C++之可调用对象
C++中的可调用对象分为以下几种: 函数 函数指针 lambda表达式 bind创建的对象 重载了函数调用运算符(即“()”)的类 函数.函数指针不再介绍.lambda表达式与bind创建的类参考—— ...
- C++中的各种可调用对象
概述 一组执行任务的语句都可以视为一个函数,一个可调用对象.在程序设计的过程中,我们习惯于把那些具有复用性的一组语句抽象为函数,把变化的部分抽象为函数的参数. 函数的使用能够极大的极少代码重复率,提高 ...
- Python中的7种可调用对象
Python中有七种可调用对象,可调用对象可使用内置函数callable来检测 一.用户自定义的函数: 使用def语句或者lambda表达式创建的函数. 二.内置函数: 使用C语言实现的函数,如len ...
- C/C++: C++可调用对象详解
C++中有几种可调用对象:函数,函数指针,lambda表达式,bind创建的对象,以及重载了函数调用符的类. 1. 函数 函数偏基础的东西,在这里不再叙述.重点讲下C++11的某些重要特性和函数指针. ...
- 深入理解Javascript中构造函数和原型对象的区别
在 Javascript中prototype属性的详解 这篇文章中,详细介绍了构造函数的缺点以及原型(prototype),原型链(prototype chain),构造函数(constructor) ...
- C#中考虑为大对象使用弱引用
1.无论怎样尽力,我们总是会使用到某些需要大量内存的数据,而这些内存并不需要经常访问.或许你需要从一个大文件中查找某个特定的值,或者算法需要一个较大的查询表.这时,你也许会采用2中不太好做法:第一种是 ...
随机推荐
- 「JSOI2015」isomorphism
「JSOI2015」isomorphism 传送门 我们还是考虑树哈希来判同构. 但是我们需要使用一些特殊的手段来特殊对待假节点. 由于是无向树,我们首先求出重心,然后以重心为根跑树哈希. 此处我们不 ...
- mysql int类型字段插入空字符串时自动转为0
mysql int类型字段插入空字符串时自动转为0 如果不想转的话可以修改配置文件 修改 my.ini 文件. # Set the SQL mode to strictsql-mode=”STRICT ...
- Jmeter_正则表达式提取器_提取单组数据
1.用处:提取登录信息/获取session或者token数值 2.举例:获取登录结果的获取:msg":"登录成功" 这个数据 3.HTTP->后置处理器->正 ...
- 初始Linux软硬链接
转载 https://blog.csdn.net/libaineu2004/article/details/85918682 用实践让你明白"软链接"和"硬链接" ...
- 【C语言】字符数组,碎碎念
存储方法: (1)字符数组赋值 ①初始化 ]={"China'} 或 ]="China' 注意:字符串可以不加{},单字符必须加 ]={,,} ②键盘输入 () char a; ...
- PCC值average pearson correlation coefficient计算方法
1.先找到task paradise 的m1-m6: 2.根据公式Dy=D1* 1/P*∑aT ,例如 D :t*k1 a:k2*k1: Dy :t*k2 Dy应该有k2个原子,维度是t: 3.依 ...
- 解决IE8不兼容 background-size
IE8下,使用background-size适应盒子大小时不兼容,效果如下图: 网上找资料,说添加如下代码可以兼容IE8 filter: progid:DXImageTransform.Microso ...
- python数组冒号取值操作
1.冒号的用法 1.1 一个冒号 a[i:j] 这里的i指起始位置,默认为0:j是终止位置,默认为len(a),在取出数组中的值时就会从数组下标i(包括)一直取到下标j(不包括j) 在一个冒号的情况下 ...
- Java 11 New Features
前言 北京时间 2018年9 月 26 日,Oracle 官方宣布 Java 11 正式发布.这是 Java 大版本周期变化后的第一个长期支持版本,非常值得关注.从官网即可下载, 最新发布的 Java ...
- XCOJ 1249: 全自动奖学金计算系统
1249: 全自动奖学金计算系统 时间限制: 1 Sec 内存限制: 64 MB提交: 305 解决: 54 标签提交统计讨论版 题目描述 宣城校区从今年开始,在原有奖学金制度上,设立专项奖学金. ...