函数指针包含函数在内存中的地址。第4章介绍了数组名实际上是数组中第一个元素的内存地址。同样,函数名实际上是执行函数任务的代码在内存中的开始地址。函数指针可以传人函数、从函数返回、存放在数组中和赋给其他的函数指针。
要演示如何使用函数指针,我们修改图5.15的冒泡排序程序,变成图5.26的程序。新程序包括main和函数bubble、swap、ascending和descending。函数bubbleSort接收ascending或descending函数的函数指针参数以及一个整型数组和数组长度。程序提示用户选择按升序或降序排序。如果用户输入1,则向函数bubble传递ascending函数的指针,使数组按升序排列。如果用户输入2,则向函数bubble传递descending函数的指针,使数组按降序排列。图5.27显示了示例的执行结果。
// Fig. 5.26: fig0526.cpp // Multipurpose sorting program using function pointers #include < iostream.h> #include < iomanip.h> void bubble( int [], const int, int (*)( int, int ) ); iht ascending( int, int ); int descending( int, int ); int main() { const int arraySize = 10; int order, counter, a[ arraySize ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; cout << "Enter 1 to sort in ascending order,\n" << "Enter 2 to sort descending order: "; cin >> order; cout << "\nData items in original order\n"; for ( counter = 0; counter < arraySize; counter++ ) cout << setw( 4 ) << a[ counter ]; if ( order == 1 ) { bubble( a, arraySize, ascending ); cout << "\nData items in ascending order\n"; else { bubble( a, arraySize, descending ); cout << "\nData items in descending order\n"; } for ( counter = 0; coun er < arraySize; counter++ ) cout << setw( 4 )<< a[ counter ] cout << endl; return 0; } void bubble( int work[ ], const int size, int (*compare)( int, int) ) { void swap( int *, int* ); for ( int pass = 1; pass < size; pass++ ) for ( int count = 0; count < size - 1; count++ ) if( (*compare)( work[ count ], work[count + 1 ] ) ) swap( &work[ count ], &work[ count + 1 ] ); } void swap( int *element1Ptr, int *element2Ptr ) { int temp; temp = *element1Ptr; *element1Ptr = *element2Ptr; *element2Ptr = temp; return b < a; // swap if b is less than a } int descending( int a, int b ) { return b > a; // swap if b is greater than a }图5.26 使用函数指针的多用途排序程序
输出结果:
Enter 1 to sort in ascending order,
Enter 2 to sort in descending order:1
Data items in original order
2 6 4 8 1O 12 89 68 45 37
Data items in ascending order
2 4 6 8 1O 12 37 45 68 89
Enter 1 to sort in ascendinq order,
En(e[ 2 to sort in descending order: 1
Data items in Oriqinal order
2 6 4 8 10 12 89 68 45 37
Dats items in ascendinQ order
89 68 45 37 12 10 9 6 4 2
图5.27 使用函数指针的多用途排序程序的执行结果
注意这里只包括类型,程序员可以加上名称.但参数名只用于程序中的说明,编译器将其忽略。
if语句中调用传人bubble的函数,如下所示:
if(( *compare )( work[ count ], work[ count + 1 ] ))
就像复引用变量指针可以访问变量值一样,复引用函数指针可以执行这个函数。
也可以不复引用指针而调用函数,如下所示:
if ( compare( work[ count ],work[ count + 1 ] ) )
直接用指针作为函数名。我们更愿意使用第一种通过指针调用函数的方法,因为它显式说明compare是函数指针,通过复引用指针而调用这个函数。第二种通过指针调用函数的方法使compare好像是个实际函数。程序用户可能搞糊涂,想看看compare函数的定义却怎么也找不到。
函数指针的一个用法是建立菜单驱动系统,提示用户从菜单选择一个选项(例如从1到5)。每个选项由不同函数提供服务,每个函数的指针存放在函数指针数组中。用户选项作为数组下标,数组中的指针用于调用这个函数。
图5.28的程序提供了声明和使用函数指针数组的一般例子。这些函数(function1、function2和function3)都定义成取整数参数并且不返回值。这些函数的指针存放在数组f中,声明如下:
void(*f[ 3 ] )(int) = { function1, function2,function3}
声明从最左边的括号读起,表示f是3个函数指针的数组,各取整数参数并返回void。数组用三个函数名(是指针)初始化。用户输入0到2的值时,用这些值作为函数指针数组的下标。函数调用如下所示:
(*f[ choice ])(choice);
调用时,f[choice]选择数组中choice位置的指针。复引用指针以调用函数,并将choice作为参数传人函数中。每个函数打印自己的参数值和函数名,表示正确调用了这个函数。练习中要开发一个菜单驱动系统。
// Fig. 5.28: fig05_28.cpp // Demonstrating an array of pointers to functions #include < iostream.h> void functionl( int ); void function2( iht ); void function3( int ); int main() { void (* f[ 3 ] )( int ) = { function1, function2, function3 }; int choice; cout << "Enter a number between 0 and 2, 3 to end: "; cin >> choice; while ( choice >= 0 && choice < 3 ) { (* f[ choice ] )( choice ); cout << "Enter a number between 0 and 2, 3 to end: "; cin >> choice; } cout << "Program execution completed." << endl; return 0; } void function1( int a ) { cout << "You entered " << a << "so function1 was called\n\n"; } void function2( int b ) { cout << "you entered " << b << "so function2 was called\n\n"; } void function3( int c ) { cout << "You entered "<< c << "so function3 was called\n\n"; }
输出结果:
Enter a number between 0 and 2, 3 to end: 0
You entered 0 so functionl was called
Enter a number between 0 and 2, 3 to end: 1
You entered 1 so function2 was called
Enter a number between 0 and 2, 3 to end: 2
You entered 2 so function3 was called
Enter a number between 0 and 2, 3 to end: 3
Program execution completed