//=====================================================================
//TITLE:
// C++ VS C#(7):指向函數的指標和委託
//AUTHOR:
// norains
//DATE:
// Thursday 17-January-2011
//Environment:
// Visual Studio 2010
// Visual Studio 2005
//Modify
// AM,Thursday 17-January-2011 初稿
// PM,Thursday 17-January-2011 修改C++調用的方式
//=====================================================================
1. 指向函數的指標和委託
開篇點題,假設我有兩個形參和傳回型別都一樣的兩個函數,如:
static int Multiply(int Param1,int Param2)<br />{<br /> return Param1 * Param2;<br />}</p><p>static int Divide(int Param1,int Param2)<br />{<br /> return Param1 / Param2;<br />}<br />
現在我不想直接調用這兩個函數,而是間接通過某種方式來進行調用。這話看起來似乎有點拗口,不直接,我們還是來換一種說法。假設我們有一個容器,而該容器能夠擷取函數的相關資訊,但我們不必去關心調用函數是什麼,只需要調用容器,讓容器去選擇相應的函數即可。
這個所謂的容器,無論是在C++還是在C#,都是存在的。那麼,我們首先從C++開始。
在C++中,這個容器的名字叫做:指向函數的指標。沒錯,就是指標。指標絕對是C++的精髓,就像萬金油一樣,放到哪裡都是真理。只不過這裡的指標是指向函數的,所以聲明起來似乎有點怪異,代碼如下:
//定義兩個變數,在函數調用時使用<br /> int a = 10;<br /> int b = 20;</p><p> //聲明一個指向函數的指標<br /> int (*pFunc)(int,int);</p><p> //將函數地址賦值給指標<br /> if(bDiv != FALSE)<br /> {<br /> pFunc = Divide;<br /> }<br /> else<br /> {<br /> pFunc = Multiply;<br /> }</p><p> //調用指向的函數<br /> pFunc(a,b);</p><p> //調用也可使用這種形式<br /> (*pFunc)(a,b);<br />
賦值好理解,和普通的賦值沒什麼區別;調用理解上也不算很難,簡單點來看也就是相當於Multiply(a,b),複雜一點的加*也可當成是擷取指標指向的函數來理解。而聲明的這個語句:int (*pFunc)(int,int),怎麼咋看咋彆扭呢?沒辦法,這個我們也改變不了,因為標準是定死的。只不過,C++有趣就有趣在這裡,你可以使用typedef來使得聲明更清晰!不信,我們一起來看:
//定義一個函數指標類型,並且該類型名為Func<br /> typedef int (*Func)(int,int);</p><p> //聲明一個指向函數的指標<br /> Func pFunc;<br />
相對之前的直接聲明,這樣的聲明是不是更加清楚?當然,代價就是多出一行typedef代碼。
至此,C++的描述就暫時告一段落,我們接下來看看C#。在C#中,是不存在指標的,自然也不會有指向函數的指標這種玩意,取而代之的是委託。委託的聲明非常類似於函數,但它不帶函數體,並且需要使用delegate關鍵字。如果以C#來實現,那麼代碼如下:
//定義一個委託FuncDelegate,其傳回型別和形參與Multiply和Divide相同<br /> delegate int FuncDelegate(int Param1, int Param2);</p><p> //聲明兩個變數,用來函數定義用<br /> int a = 10;<br /> int b = 20;</p><p> //聲明一個委託變數<br /> FuncDelegate Func;</p><p> //給委託變數賦值<br /> if (bDiv != false)<br /> {<br /> Func = new FuncDelegate(Divide);<br /> }<br /> else<br /> {<br /> Func = new FuncDelegate(Multiply);<br /> }</p><p> //調用對應的函數<br /> Func(a,b);<br />
C#中採用委託的方式,其實和C++的typedef非常相像,都是必須先定義一個類型,然後用該類型去聲明一個變數。最大的不同在賦值階段,C++只需要簡單的將函數地址賦給指標,而C#必須用new聲明一個對象,並且還要求相應的函數作為形參傳入。在這個階段,似乎C#顯得更為複雜。到了調用階段,C++和C#都可以容器後加個括弧就能完成調用,但C++還多了一種*的方式。雖然這種方式有點雞肋,但畢竟多了一種樂趣,何樂而不為呢?