C++ -函式指標

C++ -函式指標 (function pointer)

1. 普通的函式指標

函式指標 function pointer,是一個指標,指向某「特定函式型別」,函式型別由其「返回型別和參數列」決定,函式名稱並非型別的一部分。

宣告 pf 是一個函式指標,指向一個「回傳 int 且接收 2 個 int」的函式

int (*pf)(int a, int b);

這是型別,就像 int 一樣,是個型別,很笨重又不易使用,所以通常會用 typedef 定義其同義字。

typedef int (*numHandle)(int a, int b);

numHandle 是一個「函式指標的型別名稱」,該型別是個指標,指標所指的函式會「回傳 int 且接收 2 個 int」。一旦需要使用這個型別,可以寫 numHandle 而不需每次寫出完整的型別定義。

當單純使用函式名稱而不進行呼叫時,這名稱自動被視為一個函式指標。

int HandleBig(int a, int b);

任何對 HandleBig 的使用,都會被視為一個「指標」。型別是:

int (*)(int a, int b);

範例:main.cpp

#include <iostream>
using namespace std;

typedef int (*numHandle)(int a, int b);

int HandleBig(int a, int b);
int HandleSmall(int a, int b);

int HandleNum(int a, int b, numHandle handleFun);

int main()
{
	numHandle pf1 = 0;
	numHandle pf2 = HandleBig;
	pf1 = pf2;
	numHandle pf3 = &HandleBig;

	//使用函式指標呼叫函式
	cout<<pf2(3, 4)<<endl;
	cout<<(*pf3)(3, 1)<<endl;

	//把函式指標當參數傳遞
	cout<<HandleNum(4, 9, pf3)<<endl;
	cout<<HandleNum(4, 9, HandleSmall)<<endl;

	system("pause");
	return 0;
}

int HandleNum(int a, int b, numHandle handleFun)
{
	return (*handleFun)(a, b);
}

int HandleBig(int a, int b)
{
	if(a > b)
		return a;
	return b;
}

int HandleSmall(int a, int b)
{
	if(a < b)
		return a;
	return b;
}

2. 類別(class)裡的函式指標

直接使用範例

numberhandle.h

class CNumberHandle;

typedef int (CNumberHandle::*NUMHANDLE)(int a, int b);

class CNumberHandle
{
private:
	NUMHANDLE m_pfNumHandleRule[30];
	int HandleBig(int a, int b);
	int HandleSmall(int a, int b);
public:
	CNumberHandle();
	int Handle(int a, int b, int nRule);
};

numberhandle.cpp

#include "numberhandle.h"

CNumberHandle::CNumberHandle()
{
	for(int i = 0 ; i < 30 ; i++)
		m_pfNumHandleRule[i] = 0;

	m_pfNumHandleRule[0] = &CNumberHandle::HandleBig;
	m_pfNumHandleRule[1] = &CNumberHandle::HandleSmall;
}

int CNumberHandle::Handle(int a, int b, int nRule)
{
	return (this->*m_pfNumHandleRule[nRule])(a, b);
}

int CNumberHandle::HandleBig(int a, int b)
{
	if(a > b)
		return a;
	return b;
}

int CNumberHandle::HandleSmall(int a, int b)
{
	if(a < b)
		return a;
	return b;
}

main.cpp

#include <iostream>
#include "numberhandle.h"
using namespace std;

int main()
{
	CNumberHandle* pNumHandle = new CNumberHandle;

	cout << pNumHandle->Handle(3, 4, 0) << endl;
	cout << pNumHandle->Handle(3, 4, 1) << endl;

	delete pNumHandle;

	system("pause");
	return 0;
}

函式指標的致命缺點是:無法對參數和回傳值的型態進行檢查。

因為函數已經退化成指標,指標是不帶有這些型態資訊的。少了型態檢查,當參數或返回值不一致時,會造成嚴重的錯誤。編譯器和虛擬機器並不會幫我們找出函式指標這樣的致命錯誤。所以,許多新的程式語言不支援函數指標,而改用其他方式。

參考資料
http://caterpillar.onlyfun.net/Gossip/CppGossip/FunctionPointer.html
http://caterpillar.onlyfun.net/Gossip/CppGossip/MemberFunctionPtr.html

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *