多重继承、this、dynamic_cast、static_cast的问题
2017-02-17 14:32
381 查看
今天遇到一个包含如标题般多种元素掺杂的问题,不仔细揣摩还是很难发现问题的啊。
主要情景如下:
在一个需要委托,绑定到类成员函数的情况下,需要检查该对象的生命周期,便有了SafeHookManager类,该类主要是有两个函数,参数便是检查的对象的指针。
下面是我整理出来的出现问题的情况:
实际上的我的SafeHookManager::hook和SafeHookManager::unhook一般会分别出现在BaseA、BaseB、BaseC的构造和析构函数里调用,那穿进去的指针就必须child的指针。那上面的代码执行后得到如下结果:
![](https://img-blog.csdn.net/20170217141004892?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFucGFuMDA0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
第一个问题:child分别按顺序继承BaseC、BaseA、BaseB,所以BaseC的this指针和child的地址一致,BaseA、BaseB的this指针分别包含了前面类大小的偏移。
第二个问题:在构造函数里面调用dynamic_cast进行下行转换时会得到0x00000000,是因为BaseB在构造的时候,child还没有构造,所以这时动态类型检查得不到child的指针,二static_cast却可以跟进偏移计算出child的指针。
如果要正确是使用SafeHookManager::hook和SafeHookManager::unhook,类似像child这样的类就一定要继承BaseB<child>,BaseB定义如下:
主要情景如下:
在一个需要委托,绑定到类成员函数的情况下,需要检查该对象的生命周期,便有了SafeHookManager类,该类主要是有两个函数,参数便是检查的对象的指针。
void SafeHookManager::hook(void*); void SafeHookManager::unhook(void*);
下面是我整理出来的出现问题的情况:
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; }
实际上的我的SafeHookManager::hook和SafeHookManager::unhook一般会分别出现在BaseA、BaseB、BaseC的构造和析构函数里调用,那穿进去的指针就必须child的指针。那上面的代码执行后得到如下结果:
第一个问题:child分别按顺序继承BaseC、BaseA、BaseB,所以BaseC的this指针和child的地址一致,BaseA、BaseB的this指针分别包含了前面类大小的偏移。
第二个问题:在构造函数里面调用dynamic_cast进行下行转换时会得到0x00000000,是因为BaseB在构造的时候,child还没有构造,所以这时动态类型检查得不到child的指针,二static_cast却可以跟进偏移计算出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]; };
相关文章推荐
- c++多重继承下虚函数的this指针问题
- 高级多态(一):单继承存在的问题和dynamic_cast
- 关于多继承,dynamic_cast转换失败的问题
- 错误 1 error C2440: “static_cast”: 无法从“void (__thiscall CTCPDlg::* )(WPARAM,LPARAM)”转换为“LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)” 解决问题
- C++基础重温之二:static_cast, dynamic_cast, const_cast, reinterpret_cast
- 【C++专题】static_cast, dynamic_cast, const_cast探讨
- static_cast、dynamic_cast、reinterpret_cast、和const_cast
- 多重继承、虚函数、this指针偏移
- 转载---类型转换--static_cast , dynamic_cast , reinpreter_cast
- static_cast、dynamic_cast、reinterpret_cast和const_c
- 标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast和const_cast
- 标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast和const_cast
- type_cast、static_cast和dynamic_cast
- 标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast和const_cast(转载)
- static_cast, const_cast,dynamic_cast和reinterpret_cast
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast。(转)
- static_cast、dynamic_cast、reinterpret_cast、和const_cast(2)
- 标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast和const_cast(转)
- 标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast和const_cast
- 【转】使用标准C++的类型转换符:static_cast、dynamic_cast、const_cast和reinterpret_cast