1. 程式人生 > >成員函式指標:(結構+與普通函式指標之間的轉換)

成員函式指標:(結構+與普通函式指標之間的轉換)

通過記憶體拷貝(memcpy等)可以實現任意指標

間的強制轉換,但不能保證可以正常使用。

通過網上查詢發現:

函式成員指標其實與普通成員指標不同,它除了包含函式本身地址以外還包含其他資訊(例如是否為虛擬函式等),所以不能簡單的理解成員函式指標就是普通指標那樣一般佔4位元組,這個視編譯器不同而不同:例如在VS中,普通成員函式指標類似於

struct  ptr{

  int * addr;

};

而虛擬函式的結構比較複雜,它是通過this指標加索引的方式來獲取函式的真實地址,目前沒有完全明白,此不贅述。

這裡提獲取成員函式真實地址的方法:

1 .普通成員函式

通過觀察不難發現結構體的首地址就是addr的首地址,所以成員函式的入口地址其實也就是函式指標的地址,但是C++出於型別安全的考慮不允許他們轉換成其他普通指標,如:

class  test {
public:
      void print(){}
};
typedef  void  (test::*cfun)();
typedef  void  (*fun)();
cfun cf = &test::print;
fun f= cf;   //失敗,型別檢查
memcpy(&f,&cf,sizeof(fun));
f();    //成功

2. 虛擬函式

(1)通過虛擬函式表獲取

class test{
public:
       virtual void print(){}
};
typedef void  (test::*cfun)();
typedef  void  (*fun)();
test t;
int **vptr = (int**)(&t);    //vptr[0]獲取虛擬函式表地址
cfun f = vptr[0][0];   //後面那個零時虛擬函式在虛擬函式表中的索引,表示第一個虛擬函式
f();
((fun) vptr[0][0])();

通常不能用&test::print獲取虛擬函式地址,即使獲取地址也是一箇中間值或者總是返回0x1。

3. 通用的指標轉換函式

template<class T,class R>
R  convert(T t)
{
	long addr = 0;
        memcpy(&addr,&t,sizeof(long));    
        return (R)(addr);
}

但不能保證轉換的有效性。