




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第一起来学习C++的函数指针和函数对象目录函数指针函数对象总结
函数指针
以下是cstdlib库中的一个排序数组的方法qsort()的函数原型。
voidqsort(void*base,size_tnum,size_tsize,
int(*compar)(constvoid*,constvoid*));
base--指向要排序的数组的第一个元素的指针。num--由base指向的数组中元素的个数。size--数组中每个元素的大小,以字节为单位。compar--用来比较两个元素的函数。
对于可以使用常规关系运算符进行比较的类型,常规比较函数可能如下所示:
intcompareMyType(constvoid*a,constvoid*b){
if(*(MyType*)a*(MyType*)b)return-1;
if(*(MyType*)a==*(MyType*)b)return0;
if(*(MyType*)a*(MyType*)b)return1;
}
#includecstdlib
#includeiostream
intcmpfunc(constvoid*a,constvoid*b);
usingnamespacestd;
intmain(){
intvalues[]={88,56,100,2,25};
qsort(values,sizeof(values)/sizeof(int),sizeof(int),cmpfunc);
cout"排序之后的列表:"endl;
for(intn=0;nn++){
coutvalues[n]"";
return0;
intcmpfunc(constvoid*a,constvoid*b){
return(*(int*)a-*(int*)b);
}
Enterastring(emptylinetoquit):|abcEnter
Entermenuchoice:
u)uppercasel)lowercase
t)transposedcaseo)originalcase
n)nextstring
Pleaseenteru,l,t,o,orn:
|uEnter
Entermenuchoice:
u)uppercasel)lowercase
t)transposedcaseo)originalcase
n)nextstring
Pleaseenteru,l,t,o,orn:
|lEnter
abc
#includecstdio
#includecstring
#includestring
#includecctype
#includeiostream
#defineLEN81
charshowmenu();
voidshow(void(*fp)(char*),char*str);
voidToUpper(char*);//把字符串转换为大写
voidToLower(char*);//把字符串转换为小写
voidTranspose(char*);//大小写转置
voidDummy(char*);//不更改字符串
usingnamespacestd;
intmain(){
charline[LEN];
charcopy[LEN];
charchoice;
void(*pfun)(char*);//声明一个函数指针,被指向的函数接受char*类型的参数,无返回值
cout"Enterastring(emptylinetoquit):";
while(cinline){
while((choice=showmenu())!='n'){
switch(choice){//switch语句设置指针
case'u':
pfun=ToUpper;
break;
case'l':
pfun=ToLower;
break;
case't':
pfun=Transpose;
break;
case'o':
pfun=Dummy;
break;
strcpy(copy,line);//为show()函数拷贝一份
show(pfun,copy);//根据用户的选择,使用选定的函数
cout"Enterastring(emptylinetoquit):";
cout"Bye!";
return0;
charshowmenu(){
charans;
cout"Entermenuchoice:"endl;
cout"u)uppercasel)lowercase"endl;
cout"t)transposedcaseo)originalcase"endl;
cout"n)nextstring"endl;
ans=getchar();//获取用户的输入
ans=tolower(ans);//转换为小写
while(strchr("ulton",ans)==NULL){
cout"Pleaseenteru,l,t,o,orn:"endl;
ans=tolower(getchar());
returnans;
voidshow(void(*fp)(char*),char*str){
(*fp)(str);//把用户选定的函数作用于str
coutstrendl;//显示结果
voidToUpper(char*str){
while(*str){
*str=toupper(*str);
str++;
voidToLower(char*str){
while(*str){
*str=tolower(*str);
str++;
voidTranspose(char*str){
while(*str){
if(islower(*str))
*str=toupper(*str);
elseif(isupper(*str))
*str=tolower(*str);
str++;
voidDummy(char*str){
}//不改变字符串
函数对象
函数对象是专门设计用于语法与函数相似的对象。在C++中,这是通过在类中定义成员函数operator()来实现的,例如:
structmyclass{
intoperator()(inta){
returna;
}myobject;
intx=myobject(0);
它们通常用作函数的参数,例如传递给标准算法的谓词或比较函数。
标准库预先定义了些functionobject。所谓functionobject,是某种class的实例对象,这类class对functioncall运算符做了重载操作,如此一来可使functionobject被当成一般函数来使用。
functionobject实现了我们原本可能以独立函数加以定义的事物。但又何必如此呢?
主要是为了效率。我们可以令call运算符成为inline,从而消除通过函数指针来调用函数时需要付出的额外代价。
标准库事先定义了一组functionobject,分为:
算术运算(arithmetic)、关系运算(relational)和逻辑运算(logical)三大类。
以下列表中的type在实际使用时会替换为内置类型或class类型:
6个算术运算plustype,minustype,negatetype,
multipliestype,dividestype,modulestype
6个关系运算lesstype,less_equaltype,greatertype,
greater_equaltype,equal_totype,not_equal_totype
3个逻辑运算logical_andtype,logical_ortype,logic_nottype
要使用事先定义的functionobject,首先得包含相关头文件:functional
默认情况下sort()是升序排列,我们将元素降序排列:
sort(vec.begin(),vec.end(),greaterint
其中的greaterint()会产生一个未命名的classtemplateobject,传给sort()。
binary_search()期望其搜索对象先经过排序,为了正确搜索vector,就必须传给它某个functionobjectobject,供vector排序使用:
binary_search(vec.begin(),vec.end(),elem,greaterint
我们对Fibonacci数列可以做些其他操作,如:每个元素和自身相加、和自身相乘、被加到对应的Pell数列等等。做法之一是使用泛型算法transform()并搭配plusint和multipliesint。
我们必须传给transform()的参数有:
➀一对iterator,标示出欲转换的元素范围;
➁一个iterator,所指元素将应用于转换上,元素范围同➀;
➂一个iterator,所指位置(及其后面的空间)用来存放转换结果;
➃一个functionobject,表现出我们想要应用的转换操作。
以下是将Pell数列加到Fibonacci数列的写法:
transform(fib.begin(),fib.end(),//➀
pell.begin(),//➁
fib_plus_pell.begin(),//➂
plusint//➃
transform()的定义:
functiontemplatealgorithmstd::transform
unaryoperation(1)
templateclassInputIterator,classOutputIterator,classUnaryOperation
OutputIteratortransform(InputIteratorfirst1,InputIteratorlast1,
OutputIteratorresult,UnaryOperationop);
binaryoperation(2)
templateclassInputIterator1,classInputIterator2,
classOutputIterator,classBinaryOperation
OutputIteratortransform(InputIterator1first1,InputIterator1last1,
InputIterator2first2,OutputIteratorresult,
BinaryOperationbinary_op);
————————————————————————————————————————————————————
将操作顺序应用于一(1)或两(2)个范围的元素,并将结果存储在从结果开始的范围中。
(1)一元操作
将op应用于[first1,last1]范围内的每个元素,并将每个操作返回的值存储在从result开始的范围内。
(2)二元操作
使用范围[first1,last1]中的每个元素作为第一个参数,并使用范围中从first2开始的各个参数作为
第二个参数来调用binary_op。每个调用返回的值存储在从result开始的范围中。
该函数允许目标范围与其中一个输入范围相同,以便进行适当的转换。
函数对象适配器:
functionobjectlesstype期望外界传入两个值,如果第一个值小于第二个值就返回true。本例中,每个元素都必须和用户所指定的数值进行比较。理想情形下,我们需要将lesstype转化为一个一元(unary)运算符。这可通过将其第二个参数绑定(bind)至用户指定的数值完成。这么一来lesstype便会将每个元素拿出来一一与用户指定的数值比较。
真的可以做到这样吗?是的。标准库提供adapter(适配器)便应此而生。
functionobjectadapter会对functionobject进行修改操作。binderadapter(绑定适配器)会将functionobject的参数绑定至某特定值,使binary(二元)functionobject转化为unary(一元)functionobject。这正是我们需要的。
标准库提供了两个binderadapter:
bind1st会将指定值绑定至第一操作数;
bind2nd将指定值绑定至第二操作数。
如:ab,则a是第一操作数,b是第二操作数。
vectorintfilterconstvectorintvec,intval,lessintlt){
vectorintnvec;
vectorint::const_iteratoriter=vec.begin();
while((iter=find_if(iter,vec.end(),bind2nd(lt,val)))!=vec.end()){
nvec.push_back(*iter);
iter++;
returnnvec;
}
bind2nd(less,val);会把val绑定于lessint的第二个参数身上。于是,lessint会将每个元素拿来和val比较。上例第一操作数是*iter,第二操作数就是固定值val。如果*iterval则true。
find_if()的定义如下:
templateclassInputIterator,classUnaryPredicate
InputIteratorfind_if(InputIteratorfirst,InputIteratorlast,UnaryPredicatepred);
●first、last:输入迭代器到序列的初始和最终位置。使用的范围是[first,last),它包含first和last之间的所有元素,包括first指向的元素,但不包括last指向的元素。
●pred:接受范围内的元素作为参数并返回可转换为bool类型的值的【一元函数】。返回的值表明该元素是否被认为是此函数的上下文中的匹配。函数不能修改它的参数。它可以是函数指针,也可以是函数对象(functionobject)。
●返回值:指向pred不返回false的范围内第一个元素的迭代器。如果pred对所有元素都为false,则函数返回last。
这个函数模板的行为相当于:
templateclassInputIterator,classUnaryPredicate
InputIteratorfind_if(InputIteratorfirst,InputIteratorlast,UnaryPredicatepred){
while(first!=last){
if(pred(*first))returnfirst;
++first;
returnlast;
}
下面看一个泛型函数find_if()的例子:
#includeiostream//std::cout
#includealgorithm//std::find_if
#includevector//std::vector
boolIsOdd(inti){
return((i%2)==1);
intmain(){
std::vectorintmyvector;
myvector.push_back(10);
myvector.push_back(25);
myvector.push_back(40);
myvector.push_back(55);
std::vectorint::iteratorit=
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 美术设计师考试提前准备计划试题及答案
- 《下肢淋巴引流》课件
- 委托购买理财协议
- 《高级医古文:词义》课件
- 创新驱动下的研究生培养新策略与实施路径
- 产教融合推动财经人才培养的创新路径
- 纺织工程师资格考试备战攻略试题及答案
- 工程合同挂靠协议书
- 采购合同合同协议书范本
- 续签家政合同协议书
- GB/T 3452.4-2020液压气动用O形橡胶密封圈第4部分:抗挤压环(挡环)
- 王力宏-缘分一道桥-歌词
- (完整版)建筑施工技术规范
- 高校电子课件:现代管理学基础(第三版)
- 《药物学》课程教学大纲
- 艾滋病感染孕产妇所生儿童艾滋病早期诊断与抗体检测流程图
- 修改版丝竹相和
- 危险化学品企业安全标准化规范课件
- 客户退货处理流程图
- RNN+LSTM学习资料课件
- 超星尔雅学习通《组织行为学》章节测试含答案
评论
0/150
提交评论