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-


分享到:


相關文章: