【发布时间】:2012-02-11 07:55:39
【问题描述】:
在修复庞大代码库中的错误时,我观察到一种奇怪的情况,引用的动态类型从原始Derived 类型更改为Base 类型!我提供了解释问题的最少代码:
struct Base {
// some 'virtual' function
protected: // copy constructor
private: // assignment operator
};
struct Derived : Base {
... // There are few more classes between `Base` and `Derived`
... // but for simplicity, I have put direct relation
};
void foo (Base &ref)
{
SomeClass obj;
obj.pVoid = &ref; // pVoid is of void*
// ----> typeid(ref) = Derived
(*funcptr)(obj);
// ----> typeid(ref) = Base !!!
Derived *p = dynamic_cast<Derived*>(&ref); // this fails ... i.e. "p = 0"
}
funcptr 是一个函数指针 (void (*)(SomeClass&))。 funcptr 可以指向这么多函数,而且它们有自己的调用流程,所以很难调试。
很奇怪,在调用函数指针之后,ref的派生类型从Derived变成了Base。为了减轻我的工作,我怀疑从Derived到Base的对象切片,所以我将~Base()作为纯virtual并重新编译了整个源代码。但是没有编译错误,这意味着没有声明Base的对象。
refDerived 的动态类型更改为Base 并且稍后dynamic_cast 失败的潜在原因是什么?
【问题讨论】:
-
如果 typeid(ref) 在调用之后是基数,那么函数就会与对象混淆。您正在传递一个指向对象的指针,因此很容易在整个对象上写随机的东西。
-
@LokiAstari,虽然这段代码已经稳定了好几年,但你所说的是我的主要嫌疑人。
pVoid可能搞砸了,但我必须看看它是在什么情况下发生的。在此之前,我想检查一下是否遗漏了任何可能将动态类型更改为静态类型以供参考的琐碎事情。
标签: c++ dynamic-cast dynamic-typing