溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

成員函數(shù)指針的結(jié)構(gòu)以及怎么與普通函數(shù)指針之間的轉(zhuǎn)換

發(fā)布時(shí)間:2021-10-14 10:13:01 來源:億速云 閱讀:138 作者:柒染 欄目:編程語言

這篇文章給大家介紹成員函數(shù)指針的結(jié)構(gòu)以及怎么與普通函數(shù)指針之間的轉(zhuǎn)換,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

通過內(nèi)存拷貝(memcpy等)可以實(shí)現(xiàn)任意指針

間的強(qiáng)制轉(zhuǎn)換,但不能保證可以正常使用。

通過網(wǎng)上查找發(fā)現(xiàn):

函數(shù)成員指針其實(shí)與普通成員指針不同,它除了包含函數(shù)本身地址以外還包含其他信息(例如是否為虛函數(shù)等),所以不能簡(jiǎn)單的理解成員函數(shù)指針就是普通指針那樣一般占4字節(jié),這個(gè)視編譯器不同而不同:例如在VS中,普通成員函數(shù)指針類似于

struct  ptr{

  int * addr;

};

而虛函數(shù)的結(jié)構(gòu)比較復(fù)雜,它是通過this指針加索引的方式來獲取函數(shù)的真實(shí)地址,目前沒有完全明白,此不贅述。

這里提獲取成員函數(shù)真實(shí)地址的方法:

1 .普通成員函數(shù)

通過觀察不難發(fā)現(xiàn)結(jié)構(gòu)體的首地址就是addr的首地址,所以成員函數(shù)的入口地址其實(shí)也就是函數(shù)指針的地址,但是C++出于類型安全的考慮不允許他們轉(zhuǎn)換成其他普通指針,如:

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. 虛函數(shù)

(1)通過虛函數(shù)表獲取

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

通常不能用&test::print獲取虛函數(shù)地址,即使獲取地址也是一個(gè)中間值或者總是返回0x1。

3. 通用的指針轉(zhuǎn)換函數(shù)

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

但不能保證轉(zhuǎn)換的有效性。

關(guān)于成員函數(shù)指針的結(jié)構(gòu)以及怎么與普通函數(shù)指針之間的轉(zhuǎn)換就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI