您的位置:首页 > 其它

多重继承、this、dynamic_cast、static_cast的问题

2017-02-17 14:32 381 查看
今天遇到一个包含如标题般多种元素掺杂的问题,不仔细揣摩还是很难发现问题的啊。

主要情景如下:

在一个需要委托,绑定到类成员函数的情况下,需要检查该对象的生命周期,便有了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];
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  继承
相关文章推荐