成員函式指標:(結構+與普通函式指標之間的轉換)
阿新 • • 發佈:2019-02-12
通過記憶體拷貝(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);
}
但不能保證轉換的有效性。