Function Pointers, Functors, and Lamda Functions

文章推薦指數: 80 %
投票人數:10人

It is possible to pass lambda functions as arguments where function pointers are expected. Of course the signature of the lamda function should match the ... FunctionPointers Considerthefollowingfile square.cpp #include usingstd::cout; usingstd::endl; intsquare(intx) { returnx*x; } intmain() { int(*fnptr)(int); fnptr=square; cout<g++square.cpp-osquare >./square 4 Herestatementint(*fnptr)(int)declaresavariablefnptrthatcanstoreapointertoafunctionthattakesoneintargumentandreturnsanint.Intheaboveprogramsquareissuchafunction.Functionsquaretakesoneintargumentandreturnsanint.Wecanassigntheaddressofthisfunctiontovariablefnptrusingtheassignmentfnptr=square.Notethatthenameofthefunctionisalsoitsaddress.So,wedon’tneedtousethe&togettheaddressofthisfunction.Wecanthencallthefunctionsquarebyusingthevariablefnptr. Example1 Considerthefollowingfunction voidswap(float*a,float*b) { floattmp; tmp=*a; *a=*b; *b=tmp; } Wecandeclareavariabletostorethepointertofunctionswapasfollows void(*m)(float*a,float*b); Wecanthenassigntheaddressoffunctionswaptovariablemasfollows m=swap; Example2 Considerthefollowingfunction boolgt(inta,intb) { returna>b; } Wecandeclareavariabletostorethepointertofunctiongtasfollows bool(*l)(inta,intb); Wecanthenassigntheaddressoffunctiongttovariablelasfollows l=gt; Example3 Considerthefollowingfunction doublesum(doublea[],inti,intj,ints) { doublesum=0.0; for(intk=i;k<=j;k+=s){ sum+=a[k]; } returnsum; } Wecandeclareavariabletostorethepointertofunctionsumasfollows double(*n)(doublea[],inti,intj,ints) Wecanthenassigntheaddressoffunctionsumtovariablenasfollows n=sum; Functionpointersasarguments Havingvariablesthatcanstorepointerstofunctionsallowustopassfunctionsasargumentstootherfunctions.Theseisaverypowerfulfeaturethatenablesustowritecodewhereprocessingcanchangeonthefly. Considerthefollowingcode.Heredo_some_processisafunctionthatreliesuponthefunctionpassedtoitasitsargumenttodotheactuallyprocessing.Thismeansthatwecanchangethebehaviorofdo_some_processbypassingadifferentfunctionatruntime. function-ptr-arguments.cpp #include usingstd::cout; usingstd::endl; intsquare(intx) { returnx*x; } intneg(intx) { return-x; } intdo_some_process(int(*fn)(int),intx) { returnfn(x); } intmain() { intx=5; cout<g++function-ptr-arguments.cpp-oprog >./prog 25 -5 Listenerandcallbackfunctions Functionpointersarefrequentlyusedtosetuplistenerorcallbackfunctions.Thesefunctionareinvokedwhenacertaineventoccurs.Theseprovideaneasywayforausertoinjecttheirownfunctionalityintoalargersystem.Toreiteratethispointe,functionpointersareoftenusedtopassaroundprocessinginstructions. BelowyouseeanexampleofacallbackfunctionfortheGLUTlibrarythatallowsausertorespondtomouseevents. voidglutMouseFunc(void(*func)(intbutton,intstate,intx,inty)); Virtualfunctions Itisalsopossibletoavoidexplicitfunctionpointersbyusingvirtualfunctionsandpolymorphism.Virtualfunction,however,areimplementedbehindthesceneusingfunctionpointers. C++Functors Inadditiontofunctionpointersseenabove,C++alsoprovidesfunctors.Functorsareobjectsthatcanbeusedasifthesearefunctions.Functorsaremorepowerfulthangood’olfunctionpointers,sincefunctorscancarryaroundstate. Considerthecodebelow: functors.cpp #include usingstd::cout; usingstd::endl; classSquare{ public: intoperator()(intx){ returnx*x; } }; intmain() { Squarea; cout< usingstd::cout; usingstd::endl; classSquare{ public: intoperator()(intx){ returnx*x; } }; classNeg{ public: intoperator()(intx){ return-x; } }; template intdo_some_process(Tprocess,intx) { returnprocess(x); } intmain() { Squarea; Negb; cout<intdo_some_process(Tprocess,intx){...}isthatitalsoallowsustopassinfunctionsasbelow #include usingstd::cout; usingstd::endl; classSquare{ public: intoperator()(intx){ returnx*x; } }; classNeg{ public: intoperator()(intx){ return-x; } }; inttimestwo(intx) { return2*x; } template intdo_some_process(Tprocess,intx) { returnprocess(x); } intmain() { Squarea; Negb; intx=9; cout< usingstd::cout; usingstd::endl; intmain() { autofunc=[](intx)->int{returnx*x;}; intx=11; cout<int{returnx*x;}definesthelambdafunction.Here[]iscompilerspecification,indicatingthecompilerthatwearecreatingalambdafunction.()isusedtospecifytheargumentlist.Inthiscase,thisfunctiontakesoneargumentoftypeint,henceweuse(intx).->intindicatesthereturntype.Inthiscasethefunctionreturnsanint.{returnx*x;}isthefunctionbody.Herethelambdafunctioniscreatedanditspointerisassignedtovariablefunc.autoisakeywordthatcanbeusedtodefineavariable.Inthiscasethetypeofthevariableisinferedfromcontext. Syntacticsugar Itisokaytomiss()ifthefunctiontakesnoarguments. Itisokaytomiss->ifthecompilercandiscerntheretunrtype. Itispossibletocallthefunctionrightawaybyusing()attheendofthebodyasshownbelow Seetheexamplebelow. #include usingstd::cout; usingstd::endl; intmain() { intval=11; cout< usingstd::cout; usingstd::endl; intdo_some_process(intx,int(*process)(int)) { returnprocess(x); } intmain() { cout<int{returnx*x;})< usingstd::cout; usingstd::endl; intmain() { intval=11; cout< usingstd::cout; usingstd::endl; classDisk { protected: double_radius; constdouble_pi; public: Disk() :_radius(10),_pi(3.14159) {} doublearea(){ return //Notethatthefollowingisalambdafunction. // //Thereturntypeisn'tspecificed,sinceitcanbedeterminedbythe //compilerfromcontext.(itisadouble) // //Thefunctiondoesn'ttakeanyargumentseither.Notetheempty //()thattellusthatitisafunctioncall. // //Through[this]thelambdafunctioncapturesthethispointer //forthecurrentinstanceofDiskclass.Usingthisitisthen //abletoaccesstheprivatemembers(data)andmethods(functions). [this]{returnthis->_pi*this->_radius*this->_radius;}(); }; }; intmain() { intx=1,y=2,z=3; cout<int{returna+b;}(x,y)<int{x=5;returnx+y;}()<int{ /*thisstatementgivesacompileerrorx=10;*/ returnx+y;}()<int{ /*thisstatementgivesacompileerror,becauseyisn'tavailable withinthelambdafunctionreturnx+y;*/ returnx;}()<int{ /*thisstatementgivesacompileerror,becausezisn'tavailable withinthelambdafunctionreturnx+y+z;*/ y=10; returnx+y;}()< #include usingstd::cout; usingstd::endl; intmain() { std::vectorv; for(inti=0;i<10;++i)v.push_back(i*2); std::for_each(v.begin(),v.end(),[](intval){cout<



請為這篇文章評分?