今天遇到一個(gè)包含如標(biāo)題般多種元素?fù)诫s的問題,不仔細(xì)揣摩還是很難發(fā)現(xiàn)問題的啊。 主要情景如下: 在一個(gè)需要委托,綁定到類成員函數(shù)的情況下,需要檢查該對象的生命周期,便有了SafeHookManager類,該類主要是有兩個(gè)函數(shù),參數(shù)便是檢查的對象的指針。
void SafeHookManager::hook(void*);void SafeHookManager::unhook(void*);下面是我整理出來的出現(xiàn)問題的情況:
class BaseA{public: virtual void funA(){} BaseA(){ std::cout<<"BaseA:"<<this<<" static_cast:"<<static_cast<void*>(this)<<std::endl; } int a0;};template<typename T>class BaseB{public: virtual void funB(){} BaseB(){ std::cout<<"BaseB:"<<this<<" static_cast:"<<static_cast<void*>(this)<<" static_cast T:"<<static_cast<T*>(this)<<" dynamic_cast T:"<<dynamic_cast<T*>(this)<<std::endl; } char b[20];};class BaseC{public: virtual void funC(){} BaseC(){ std::cout<<"BaseC:"<<this<<" static_cast:"<<static_cast<void*>(this)<<std::endl; } int c;};class child:public BaseC,public BaseA,public BaseB<child>{public: void funB() override {} child(){ std::cout<<"child:"<<this<<" static_cast:"<<static_cast<void*>(this)<<std::endl; }};int main(){ child *pChild = new child; BaseB<child>* pB = static_cast<BaseB<child>*>(pChild); std::cout<<"child:"<<pChild<<" BaseB:"<<pB<<" dynamic_cast T:"<<dynamic_cast<child*>(pB)<<std::endl; return 0;}實(shí)際上的我的SafeHookManager::hook和SafeHookManager::unhook一般會分別出現(xiàn)在BaseA、BaseB、BaseC的構(gòu)造和析構(gòu)函數(shù)里調(diào)用,那穿進(jìn)去的指針就必須child的指針。那上面的代碼執(zhí)行后得到如下結(jié)果: 
第一個(gè)問題:child分別按順序繼承BaseC、BaseA、BaseB,所以BaseC的this指針和child的地址一致,BaseA、BaseB的this指針分別包含了前面類大小的偏移。 第二個(gè)問題:在構(gòu)造函數(shù)里面調(diào)用dynamic_cast進(jìn)行下行轉(zhuǎn)換時(shí)會得到0x00000000,是因?yàn)锽aseB在構(gòu)造的時(shí)候,child還沒有構(gòu)造,所以這時(shí)動態(tài)類型檢查得不到child的指針,二static_cast卻可以跟進(jìn)偏移計(jì)算出child的指針。
如果要正確是使用SafeHookManager::hook和SafeHookManager::unhook,類似像child這樣的類就一定要繼承BaseB<child>,BaseB定義如下:
template<typename T>class BaseB{public: BaseB(){ SafeHookManager::hook(static_cast<T*>(this)) } ~BaseB(){ SafeHookManager::unhook(static_cast<T*>(this)) } char b[20];};新聞熱點(diǎn)
疑難解答