C/C++: C++可调用对象详解
std::initializer_list<T>{ };
可以使用列表初始化来进行初始化,T表示的是参数类型,initializer_list可以被拷贝,但是一定要注意的是,它是一种引用拷贝,也就是说拷贝后新的list和被拷贝的list是的元素都是共享的。
2. 第二种是省略符形参,熟悉C的人对这个也应该很熟悉了,就是printf和scanf这些函数所用的方法。
void print(int, ...);
省略符形参其实是为了方便访问特殊的C代码而设计的,这些代码其实是使用了标准库varargs的功能(C标准库)。
#include <stdarg.h>
void method(int i, ...)
{
int v;
va_list params;//声明可变參数列表
va_start(params, i); //依据可变參数前的參数获得可变參数的起始地址
do {
v = va_arg(params, int); //从可变參数列表中获得參数的值,类型为int
printf("%d", v);
} while (v != );
va_end(params);
} void format(const char* format, ...)
{
char buf[];va_list params;
va_start(params, format);
vsnprintf_s(buf, , , format, params);
va_end(params);
printf("%s", buf);
}
typedef int arr[];//typedef方法
using Arr = int[];//别名用法
Arr *func0(int i);
int(*func1(int i))[];
auto func2(int i) -> int(*)[];
//尾置返回类型(明确知道函数返回的指针指向什么地方)
int odd[] = { ,,,, };
int even[] = { ,,,, }; decltype(odd) *arrPtr(int i)
{
return (i % ) ? &odd : &even;
}
const std::string &shortString(const std::string &s1, const std::string &s2)
{
return s1.size() <= s2.size() ? s1 : s2;
}
std::string &shortString(std::string &s1, std::string &s2)
{
auto &r = shortString(const_cast<const std::string &>(s1),
const_cast<const std::string &>(s2));//注意这里的shortSring必须要const_cast
//因为在这里s1和s2都是非常连版本,而编译器会优先选择非常量版本进行调用,导致递归出错
return const_cast<std::string &>(r);
}
const_cast和重载(注意自己一定要清楚const_cast之前的变量是不是const,如果是const,那么就会产生未定义的行为)。
size_t wd = ;char def = ' ';
size_t ht();
string screen(size_t = ht(), size_t = wd, char = def);
string window = screen();//调用screen(ht(), 80 ' ') void f2()
{
def = '*';
size_t wd = ;
window = screen();//调用screen(ht(), 80 '*')
}
constexpr size_t scale(size_t cnt)
{
using test = int;
return cnt * ;
}
int t;
int arr[scale()];
auto ret = scale(t);
scale(100)返回的是一个常量表达式,但是scale(t)则返回的就是size_t类型。
- 精确匹配(实参类型和形参类型是一样的,或者实参从数组类型或者函数类型转换成对应的指针类型,向实参添加顶层const或者从实参中消除顶层const)(对于底层const,如果同时定义了非常量版本和常量版本,如果传入非常量,那么就会调用非常量版本函数,如果传入的实参为常量版本,则会调用常量版本的函数)。
- 通过const实现的匹配
- 通过类型提升来实现的匹配(比如整型提升)。
- 通过算术转换或者指针转换实现的匹配。
- 通过类类型转来来匹配的转换。
int(*pf)(std::string s1);
int test(std::string s1) { return ; }
int(*pf)(std::string s1);
pf = test;
pf = &test;
test(std::string());
(*test)(std::string());
auto foo() -> int(*)(std::string s1);
decltype(test) *getfcn();
3. lambda表达式(匿名函数对象,一个C++的语法糖)
一个lambda表达式表示一个可调用的代码单元,我们可以将其理解为有一个未命名的内联函数,与任何函数类似,一个lambda具有一个返回类型,一个参数列表和一个函数体,并且这个函数体是可以定义在函数内部的。
auto fcn = [] {return ;};//定义了一个可调用对象fcn为一个lambda表达式
//忽略参数列表,忽略返回类型(都为空)
#include <algorithm>
#include <iostream>
#include <vector> using std::vector;
using std::find_if;
using std::for_each;
using std::cout;
using std::endl; void searchSegment(vector<int> nums, const int floorSize, const int ceilSize)
{
std::stable_sort(nums.begin(), nums.end(),
[](const int &a, const int &b) { return a < b;});//注意sort和stable_sort当comp(x,x)的时候一定要返回false
auto segFloorIndex = find_if(nums.begin(), nums.end(),
[&floorSize](const int &a) ->bool { return a >= floorSize; });
auto segCeilIndex = find_if(nums.begin(), nums.end(),
[&](const int &a) { return a >= ceilSize; });
cout << "The size of the segment is " << segCeilIndex - segFloorIndex << endl;
}
捕获分值捕获和引用捕获,引用捕获就在变量前面加&就可以了,引用捕获可以解决某些类不能被拷贝的问题(比如输入输出流),另外捕获还可以是隐式的,比如我上面的算segCeilIndex的时候,就可以直接一个&就代表捕获所有的引用参数了。
int v;
auto f = [v]()mutable {return ++v; };
我们上面看到lambda表达式可以很好地解决标准库有些函数的谓词问题,现在我们想问的问题是,如果不想用lambda来实现谓词的转换,我只想用函数,那么怎么办呢?标准库提供了一个很好的办法,那就是bind函数(C++11 Feature)。(定义在头文件functional里面)。
bool findMin(const int &a, const int &value)
{
return a >= value;
}
segFloorIndex = find_if(nums.begin(), nums.end(), bind(findMin, _1, floorSize));
segCeilIndex = find_if(nums.begin(), nums.end(), bind(findMin, _1, ceilSize));
其中_1(类似的还有_2,_3....)这个东西为占位符(有点像汇编的那个,定义在std的placeholders的作用域),表示的是外面的可以传入的参数,参数从左到右依次填入_1,_2...中(比如如果有调用对象G的定义为auto G= bind(f, _2, a, _1 ),调用G(x,y)实际上是f(Y,a,x ),用这个拿来交换参数位置)。
C++的类厉害的地方之一就是可以重载函数运算,就是retType operator( )(parameter...){ }的形式,这种重载了函数调用符的类可以直接让我们用类名来实现函数的功能,比如:
class FunctonalClass
{
public:
bool operator()(const int &a, const int &value)
{
return a >= value;
}
};
class AnonymityFunctional
{
public:
AnonymityFunctional(const int &v) :value(v) { }
bool operator()(const int &a) const { return a >= value; }
private:
const int &value;
};
segFloorIndex = find_if(nums.begin(), nums.end(), AnonymityFunctional(floorSize));
segCeilIndex = find_if(nums.begin(), nums.end(), AnonymityFunctional(ceilSize));
上面说了5种可调用对象,有时候我们想实现某些设计模式的时候,我们想用一个统一接口来调用这些对象,实现可调用对象表,但是这些可调用对象本质上类型都是不一样的,如何把他们统一起来呢?答案就是使用标准库模板function<T>,
std::function<bool(const int &)>
bool fcn(const int &a){ return a; }
class FunctionTest
{
public:
FunctionTest() = default;
bool getWhat(const int &a)const { return true; }
bool getS()const { return true; }
};
std::function<bool(const int &)> f1 = [](const int &a) { return a ; };
std::function<bool(const int &)> f2 = Test();
std::function<bool(const int &)> f3 = fcn;
最常见的就是把一些函数放进map里面,那样我们就可以根据关键字来调用对象了,非常方便。不过需要注意的是,如果函数是重载过的,那我们就不能直接塞函数名进去了(会产生二义性),这个时候就要自己创建要放入函数的函数指针,再创建function。
bool fcn() { return true; }
bool fcn(const int &a){ return a; }
bool(*pfcn)(const int &) = fcn;
std::function<bool(const int &)> f3 = pfcn;
class FunctionTest
{
public:
FunctionTest() = default; bool getWhat(const int &a)const { return true; }
bool getS()const { return true; }
};
FunctionTest haha, *phaha = &haha; bool (FunctionTest::*pf)(const int &) const;//先定义一个指针
pf = &FunctionTest::getWhat;//指针指向类的什么函数 auto ret = (haha.*pf)(floorSize);
auto ret1 = (phaha->*pf)(ceilSize);
auto pf = &FunctionTest::getWhat;
std::function<bool(const FunctionTest *, const int &)> f4(&FunctionTest::getWhat);
这里我们发现了要生成成员函数的可调用对象必须带对象,所以生成的可调用对象都必须带类的对象,这很符合成员函数指针的要求——必须绑定对象,事实上,当我们使用这样的可调用对象的时候,就相当于把this指针先传给第一个参数了,所以这个function对象本质上是需要两个参数的!不能用于find_if。
auto f = std::mem_fn(&FunctionTest::getWhat);
C/C++: C++可调用对象详解的更多相关文章
- mvc-servlet---ServletConfig与ServletContext对象详解(转载)
ServletConfig与ServletContext对象详解 一.ServletConfig对象 在Servlet的配置文件中,可以使用一个或多个<init-param>标签为s ...
- django中request对象详解(转载)
django中的request对象详解 Request 我们知道当URLconf文件匹配到用户输入的路径后,会调用对应的view函数,并将 HttpRequest对象 作为第一个参数传入该函数. ...
- jQuery的deferred对象详解(一)
最近一段时间,都在研究jquery里面的$.Deffered对象,几天都搞不明白,其中源码的运行机制,网上查找了相关的资料,<jQuery的deferred对象详解>阮一峰老师的文章,里面 ...
- ActiveXObject对象详解
一.什么是 ActiveX 控件? ActiveX 控件广泛用于 Internet.它们可以通过提供视频.动画内容等来增加浏览的乐趣.不过,这些程序可能出问题或者向您提供不需要的内容. ...
- js对象详解(JavaScript对象深度剖析,深度理解js对象)
js对象详解(JavaScript对象深度剖析,深度理解js对象) 这算是酝酿很久的一篇文章了. JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕 ...
- python引用和对象详解
python引用和对象详解 @[马克飞象] python中变量名和对象是分离的 例子 1: a = 1 这是一个简单的赋值语句,整数 1 为一个对象,a 是一个引用,利用赋值语句,引用a指向了对象1. ...
- Java WebService接口生成和调用 图文详解>【转】【待调整】
webservice简介: Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的.专门的第三方软件或硬件, 就可相互交换数据或集成.依据Web Service规范实施的应用之间 ...
- [转] jQuery的deferred对象详解
jQuery的开发速度很快,几乎每半年一个大版本,每两个月一个小版本. 每个版本都会引入一些新功能.今天我想介绍的,就是从jQuery 1.5.0版本开始引入的一个新功能----deferred对象. ...
- jQuery的deferred对象详解(转)
jQuery的开发速度很快,几乎每半年一个大版本,每两个月一个小版本. 每个版本都会引入一些新功能.今天我想介绍的,就是从jQuery 1.5.0版本开始引入的一个新功能----deferred对象. ...
随机推荐
- 【UOJ #35】后缀排序 后缀数组模板
http://uoj.ac/problem/35 以前做后缀数组的题直接粘模板...现在重新写一下模板 注意用来基数排序的数组一定要开到N. #include<cstdio> #inclu ...
- 【BZOJ 3445】【Usaco2014 Feb】Roadblock
http://www.lydsy.com/JudgeOnline/problem.php?id=3445 加倍的边一定在最短路上(否则继续走最短路). 最短路长度是O(n)的,暴力扫最短路上的每条边, ...
- React数据流和组件间的沟通总结
今天来给大家总结下React的单向数据流与组件间的沟通. 首先,我认为使用React的最大好处在于:功能组件化,遵守前端可维护的原则. 先介绍单向数据流吧. React单向数据流: React是单向数 ...
- windows server 2008 各版本号下载地址(微软官网)
前言: 微软官网上下载系统的镜像文件要远比百度网盘下载起来得更快. Windows Server 2008 32-bit Standard(标准版)
- JavaScript事件详解-Zepto的事件实现(二)【新增fastclick阅读笔记】
正文 作者打字速度实在不咋地,源码部分就用图片代替了,都是截图,本文讲解的Zepto版本是1.2.0,在该版本中的event模块与1.1.6基本一致.此文的fastclick理解上在看过博客园各个大神 ...
- 2017年"程序媛和工程狮"绝对不能忽视的编程语言、框架和工具
2017年"程序媛和工程狮"绝对不能忽视的编程语言.框架和工具 在过去的一年里,软件开发行业继续大踏步地向前迈进.回顾 2016 年,我们看到了更多新兴的流行语言.框架和工具, ...
- 【poj3744】 Scout YYF I
http://poj.org/problem?id=3744 (题目链接) 题意 给出n个雷,分别在 a[1]...a[n] ,走一步概率为 p ,走两步概率为 1-p ,一开始在 1 号位置,问安全 ...
- lightbox使用
使用方法: 1.在页面头部包含 lightbox.js 文件并加载 lightbox.css 样式表文件 <script type="text/javascript" src ...
- MVC 总结
以下内容摘自 PHP for Absolute Beginners, Thomas Blom Hansen & Jason Lengstorf The model-view-controlle ...
- ffmpeg 音频转换(amr2mp3)
yasm:http://yasm.tortall.net/Download.html(汇编器,新版本的ffmpeg增加了汇编代码) lame:http://lame.sourceforge.net/d ...