1. 程式人生 > >C++類成員函式做引數以及轉換呼叫

C++類成員函式做引數以及轉換呼叫

最近專案過程中由於程式碼重構,想精簡程式碼的時候發現類的成員函式重構出現了無法賦值給封裝函式作為引數的問題。有一定基礎的coder應該都知道其中有隱含this成員的原因,但在用法上網上資料雖多但沒有一個較為具體的程式範例,於是我寫下了下面一段程式碼,供大家分析參考:



#include "stdafx.h"
#include <assert.h>

class Test
{
public:
typedef void (Test::*DATAFUNC) (); // 範例1,類內部的typeDef函式宣告,屬於Test成員,宣告時必須加Test宣告作用域,且賦值的函式必須為Test成員(核心原理為類的成員函式實際上引數壓棧時多了一個this指標,所以匹配時會做型別檢查)
typedef void (*DATAFUNC2) ();      // 範例2,類內部的typeDef函式宣告,屬於Test成員,宣告時必須加Test宣告作用域,且賦值的函式必須不為Test成員

Test(){mi =0;}
~Test(){};

void testfunc() {printf("interval testfunc\n");}
protected:
private:
int mi;
};


typedef void (Test::*DATAFUNC1) (); //範例3,類外部的typeDef函式宣告,不屬於Test成員,宣告時不能加Test宣告作用域,賦值的函式必須為Test成員
typedef void (*FUNC)(); //範例4,類外部的typeDef函式宣告,不屬於Test成員,宣告時不能加Test宣告作用域,賦值的函式必須不為Test成員

void testfunc2() {printf("external testfunc2\n");}

int _tmain(int argc, _TCHAR* argv[])
{
Test t;
Test::DATAFUNC pfunc   = NULL;    
Test::DATAFUNC2 pfunc2 = NULL;
DATAFUNC1     pfunc1   = NULL;
FUNC          pf       = NULL;


printf("the addr of Test::testfunc is %x\n",&Test::testfunc);
//printf("the addr of t.testfunc is %x\n",&(t.testfunc)); //物件沒有成員函式地址,類才有成員函式地址

//範例1
pfunc = &Test::testfunc;  //不必要也不能使用物件的成員函式,因為成員函式都屬於類本身,在構建物件之前就會構建。
//pfunc();                  //無法輸出,pfunc的實際指向是類的成員,必須依賴類的物件或者靜態化來輸出;
(t.*pfunc)();               //輸出
//pfunc = &testfunc2;       //無法轉換,賦值函式必須為類成員型別

//範例2
//pfunc2 =  &Test::testfunc;  //無法轉換,賦值函式必須為全域性void (*) ()型別,不能為類成員
pfunc2   = &testfunc2;        //&可用可不用,全域性函式名是表示函式地址的
pfunc2();                     //可以輸出,指標實際指向的不是類的成員。

//範例3
pfunc1 =&Test::testfunc;   //雖然typedef本身
//pfunc1();
(t.*pfunc1)();             //同樣可以藉助類物件輸出,就是很彆扭!不能直接呼叫
//pfunc1  = testfunc2;

//範例4
//pf  = &Test::testfunc;     //FUNC型別也不是類成員,無需this指標
//pf();                        //可以輸出,但注意測試並沒有被賦值
pf = &testfunc2;
pf();
 
return 0;
}


//解決將一個類成員函式指向函式指標的技術可以用Trunk技術
//http://blog.csdn.net/ax614/article/details/6684017