C++|函数指针做参数,让函数更一般化(选择排序:升序或降序)

函数可以实现代码重用和封装,参数可以让函数更具一般化及函数之间发生关系(输入与输出),同时,有参数的函数可以实现递归调用,这就是函数的作用。

为了实现更一般的泛化,如果函数的参数数量不同,可以使用函数重载,如果函数参数类型不同,可以使用函数模板或函数重载。但如果几个函数只有几行代码不同,其它绝大多数代码都相同,怎么办?函数重载和函数模板都不能解决问题,可将这几行不同的代码分别抽出来,写成函数A、B、C等,再将共同的代码写成一个函数F,在F的参数中包含一个函数指针,去调用A、B、C即可。

举过例子,想通过函数实现数组的升序或降序排列(如果用两个函数实现,可能只有一行代码不同),是把代码写死再在需要时修改其中的一行代码(硬编码)?还是写一个包含比较语句的函数和一个排序函数,在排序函数中调用包含比较语句的函数,这样只需修改包含比较语句的函数,保证了排序函数的稳定性。

更一般的方法是,写两个包含比较语句的函数和一个排序函数,在排序函数的参数列表中包含一个函数指针来引用包含比较语句的函数,在调用时,参数指向具体的包含比较语句的函数。

以下就是以上三种方法的代码:(在排序函数分别写了三条函数头、函数体中的比较语句,以及函数调用的语句(运行时注释掉另两条 ),当然还有包含比较语句的函数。)

#include <iostream>
using namespace std;
#include <algorithm> // swap()

bool ascending(int x, int y)
{
return x > y; // swap if the first element is greater than the second
}

bool descending(int x, int y)
{
return x < y; // swap if the second element is greater than the first
}

void printarr(int *arr, int size)
{
for (int index=0; index < size; ++index)
cout << arr[index] << " ";
cout << '\\n';
}

//void SelectionSort(int *arr, int size) // 1.1 选择排序,直接比较(硬编码)
//void SelectionSort(int *arr, int size) // 1.2 选择排序,调用函数比较(较软编码)
void selectionSort(int *arr, int size, bool (*compFcn)(int, int)) // 1.3 选择排序,调用函数指针比较(软编码)
{
for (int start = 0; start < size; ++start)
{
int small = start;
for (int curr = start + 1; curr < size; ++curr)//find the index of smallest value of array member
{
//if (arr[small] > arr[curr]) // 2.1 直接比较
\t\t\t//if (ascending(arr[small], arr[curr])) // 2.2 调用函数比较
\t\t\tif (compFcn(arr[small], arr[curr])) // 2.3 调用函数指针比较
small = curr;
}

swap(arr[start], arr[small]);
}
}
int main()
{
int arr[9] = { 3, 7, 9, 5, 6, 1, 8, 2, 4 };
//SelectionSort(arr, 9); // 3.1 调用函数(直接比较)

\t//printarr(arr, 9);
//SelectionSort(arr, 9); // 3.2 调用函数(调用函数比较)
\t//printarr(arr, 9);
\tselectionSort(arr, 9, ascending); // 3.3 调用函数(调用函数指针比较)
\tprintarr(arr, 9);
\tselectionSort(arr, 9, descending); // 3.3 调用函数(调用函数指针比较)
\tprintarr(arr, 9);
\tsystem("pause");
return 0;
}
/*
1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1
*//<algorithm>/<iostream>

函数指针用做函数参数,能够更好地实现函数的灵活性和一般性。函数指针用做参数时其指向的函数也称为回调函数。

另外,可以使用函数指针数组来实现菜单或菜单选择。

非静态成员函数指针做参数及使用稍微特殊一点:

void CAssistantsDlg::HaveText(void (CAssistantsDlg::*f)())

{

//……

(this->*f)();

//……

}

静态成员函数指针的使用与普通函数指针的使用方法差不多。

-End-


分享到:


相關文章: