C++ 传递、储存函数Part 1:Function Pointer
本文主要讲解C++可以用来储存、传递一个函数(function)的一些方法;当然,主要就是function pointer 和function object 了~为什么要做这件事呢?其实如果妥善利用的,这类的功能是相当实用,不但可以减少不少程序码的量的,同时更可以减少程序码维护所需要的时间。
而首先,这一篇就先来大概介绍一下C 的funciton pointer(函式指针、pointer to function)了~
Function Pointer 基本范例
顾名思义,他就是指到function 的指针。下面是一个简单的范例:
- int power2( int v )
- {
- return v * v;
- }
- void custom_for_each( int *pArray, unsigned int size, int (*op)( int ) )
- {
- for ( unsigned int i = 0; i < size; ++ i )
- pArray[i] = (*op)( pArray[i] ) ;
- }
- int main( int argc, char * argv[] )
- {
- int size = 10;
- int * pArray = new int [ size ];
- for ( unsigned int i = 0; i < size; ++ i )
- pArray[i] = i;
- custom_for_each( pArray, size, &power2 );
- for ( unsigned int i = 0; i < size; ++ i )
- printf( "%d, " , pArray[i] );
- delete [] pArray;
- return 0;
- }
在这个例子里,除了main()以外,还有定义了两个function:power2()和custom_for_each()。
其中,power2()相当简单,就是传入一个整数,然后计算他的平方后传回来。
custom_for_each()这个函式则就是这边的重点,它的用途是传入一个整数的数组pArray和他的大小size,以及一个function pointer op;而这边这个function pointer的写法,就是「int (* op)( int )」,它代表了一个名为op的pointer,指到一个「接受一个整数当作参数、并回传一个整数的function」。
在custom_for_each()的内容部分,则就是一个循环,把pArray里的每一项,都经过op做计算,并写回pArray里;而传递op的方法,基本上就是「(*op)( pArray [i] )」,也就是像一般的指针一样,在前面加上「*」了~
而实际上要怎么使用这两个函式呢?只要在传递custom_for_each()的时候,把power2()的位址当作第三个参数传进去就可以了!完整写出来,就是「custom_for_each( pArray, size, &power2 );」了。而实际上,只要是「接受一个整数当作参数、并回传一个整数的function」,都是可以以这样的形式当作参数传进custom_for_each()使用的~
这样写的好处,在于可以把function拆开成更小的元件,让他们可以更方便地组合、使用,有效地增加程序码的可重复使用性。现在范例里只有power2()一个函式或许感觉不太出来,但是如果我们又去额外写了其他他的函式的话,就比较看的出来了~比如说,假设我们现在有下面这六个function :
- int plus_one( int v );
- int power2( int v );
- int power3( int v );
- int power4( int v );
- void custom_for_each( int *pArray, unsigned int size, int (*op)( int ) );
- void custom_for_each_2D( int **pArray, int sizeX, int sizeY, int (*op)( int ) );
应该就比较感觉得出来这样写的好处了!因为前面四个计算用的function可以任意传给custom_for_each()或来当作custom_for_each_2D()参数,在这个状况下,就是有4 * 2、共有八种组合了~而如果函式的内容复杂、数量在更多的话,这样不但可以减少许多本来需要重复撰写的程序码,也可以有效降低程序码维护的时间。
使用typedef 加强可读性
虽然这样就可以使用function pointer了,但是说实话看起来实在很丑、很难阅读;「int (*op)(int)」这样的写法,真的很难一眼就看出来哪个才是变量。
所以,如果要经常性地使用某种形式的function pointer的时候,其实可以考虑透过「typedef」的方式,帮 ??这种比较复杂的function pointer型别,定义出一个比较简单、一般的型别名称来用。例如以上面的例子来说,就可以改写成:
- typedef int (* CustomOperator )( int );
- //void custom_for_each( int *pArray, unsigned int size, int (*op)( int ) )
- void custom_for_each( int *pArray, unsigned int size, CustomOperator op )
也就是可以先透过第一行的「typedef int (*CustomOperator)( int );」,让CustomOperator 变成是一个function pointer的型别,而之后就可以把它当作一般的型别来使用了~像custom_for_each()的声明,就可以直接用「CustomOperator op」来代替本来的「int (*op)( int )」!这样看起来,就简单易懂多了~
Function Pointer 的数组
而在某些情况下,我们或许会需要使用到function pointer 的数组,这时候该怎么写呢?基本的写法,是如同下面这样的形式:
- int (*op[10])( int );
- for ( int i = 0; i < 10; ++ i )
- op[i] = &power2;
在这里,「int (*op[10])( int );」就是会声明出一个大小是10的function pointer数组。在指定它里面每一项的值的时候,都和本来的function pointer写法一样;不过在使用的时候,只要写「op[1]( 10 )」这样就可了,不用再加上星号(其实就和一般的数组意义一样)。
当然,这样看起来还是很难阅读,所以我们还是可以用typedef 的方法,来加强程序的可读性~也就是可以将上面的程序码修改为:
- typedef int (* CustomOperator )( int );
- CustomOperator op[10];
- for ( int i = 0; i < 10; ++ i )
- op[i] = &power2;
这样看起来,function pointer 就更像一般的变量、更容易阅读、使用了!
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
