5.11 函数指针
函数指针包含函数在内存中的地址。第4章介绍了数组名实际上是数组中第一个元素的内存地址。同样,函数名实际上是执行函数任务的代码在内存中的开始地址。函数指针可以传人函数、从函数返回、存放在数组中和赋给其他的函数指针。
要演示如何使用函数指针,我们修改图 5.15 的冒泡排序程序,变成图 5.26 的程序。新程序包括 main 和函数 bubble、swap、ascending 和 descending。函数 bubbleSort 接收 ascending 或 descending 函数的函数指针参数以及一个整型数组和数组长度。程序提示用户选择按升序或降序排序。如果用户输入1,则向函数 bubble 传递ascending 函数的指针,使数组按升序排列。如果用户输入 2,则向函数 bubble 传递 descending 函数的指针,使数组按降序排列。图 5.27 显示了示例的执行结果。
1 // Fig. 5.26: fig0526.cpp
2 // Multipurpose sorting program using function pointers
3 #include <iostream.h>
4 #include <iomanip.h>
5
6 void bubble( int [], const int, int (*)( int, int ) );
7 iht ascending( int, int );
8 int descending( int, int );
9
10 int main()
11 {
12 const int arraySize = 10;
13 int order,
14 counter,
15 a[ arraySize ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 };
16
17 cout << "Enter 1 to sort in ascending order,\n"
18 << "Enter 2 to sort descending order: ";
19 cin >> order;
20 cout << "\nData items in original order\n";
21
22 for ( counter = 0; counter < arraySize; counter++ )
23 cout << setw( 4 ) << a[ counter ];
24
25 if ( order == 1 ) {
26 bubble( a, arraySize, ascending );
27 cout << "\nData items in ascending order\n";
29 else {
30 bubble( a, arraySize, descending );
31 cout << "\nData items in descending order\n";
32 }
33
34 for ( counter = 0; coun er < arraySize; counter++ )
35 cout << setw( 4 )<< a[ counter ]
36
37 cout << endl;
38 return 0;
39 }
40
41 void bubble( int work[ ], const int size,
42 int (*compare)( int, int) )
43 {
44 void swap( int *, int* );
45
46 for ( int pass = 1; pass < size; pass++ )
47
48 for ( int count = 0; count < size - 1; count++ )
49
50 if( (*compare)( work[ count ], work[count + 1 ] ) )
51 swap( &work[ count ], &work[ count + 1 ] );
52 }
53
54 void swap( int *element1Ptr, int *element2Ptr )
55 {
56 int temp;
57
58 temp = *element1Ptr;
59 *element1Ptr = *element2Ptr;
60 *element2Ptr = temp;
65 return b < a; // swap if b is less than a
66 }
67
68 int descending( int a, int b )
69 {
70 return b > a; // swap if b is greater than a
71 }
图 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 作为参数传人函数中。每个函数打印自己的参数值和函数名,表示正确调用了这个函数。练习中要开发一个菜单驱动系统。
1 // Fig. 5.28: fig05_28.cpp
2 // Demonstrating an array of pointers to functions
3 #include <iostream.h>
4 void functionl( int );
5 void function2( iht );
6 void function3( int );
7
8 int main()
9 {
10 void (* f[ 3 ] )( int ) = { function1, function2, function3 };
11 int choice;
12
13 cout << "Enter a number between 0 and 2, 3 to end: ";
14 cin >> choice;
15
16 while ( choice >= 0 && choice < 3 ) {
17 (* f[ choice ] )( choice );
18 cout << "Enter a number between 0 and 2, 3 to end: ";
19 cin >> choice;
2O }
21
22 cout << "Program execution completed." << endl;
23 return 0;
24 }
25
26 void function1( int a )
27 {
28 cout << "You entered " << a
29 << "so function1 was called\n\n";
30 }
31
32 void function2( int b )
33 {
34 cout << "you entered " << b
35 << "so function2 was called\n\n";
34 }
37
38 void function3( int c )
39 {
40 cout << "You entered "<< c
41 << "so function3 was called\n\n";
42 }
输出结果:
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
图 5.28 声明和使用函数的指针数组