c++ - 在什么情况下,dynamic_cast<> 可能会失败?

标签 c++ dynamic-cast dynamic-typing

在修复庞大代码库中的错误时,我观察到一种奇怪的情况,引用的动态类型从原始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 对象。

ref Derived 的动态类型更改为 Base 以及 dynamic_cast 的潜在原因是什么> 后来失败了?

最佳答案

我不相信上面的代码与实际情况相同,因为代码示例无法编译!您不能隐式转换 Base*dynamic_cast<Base*>(&ref) 产生至Derived* .

也就是说,假设 typeid() 的输出实际上是正确的,对于引用更改的类型 ID 有一些可行的解释。所有这些都表明程序中存在某种形式的错误:

  1. 被调用的函数会销毁对象,例如通过调用道德上的等价物 dynamics_cast<Base*>(obj.pVoid)->~Base() .
  2. 被调用的函数在obj.pVoid指向的地址构造一个新对象。使用放置new ,即类似这样的:new(obj.pVoid) Base() .
  3. 某些内容正在覆盖内存,导致留下 Base引用位置中的对象。
  4. 可能还有更多原因......

就我个人而言,我会赌第二种情况是情况,即一个对象被构造到该位置。显然,如果没有看到被调用的函数,就无法判断。

关于c++ - 在什么情况下,dynamic_cast<> 可能会失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9238711/

相关文章:

scala - 从 Any 到 Dynamic 的隐式转换

c++ - 初学者引用类型参数混淆

c++ - 在 Linux 中运行 exe

javascript - 多态内联缓存如何与可变类型一起工作?

c++ - C++中的向上转型和向下转型

c++ - 没有转换的 dynamic_cast 类型检查功能?

static-typing - 静态类型和动态类型的定义

c++ - 如何从进程内部确定 CPU 和内存消耗

c++ - std::map 获取值 - 查找与手工制作的循环

c++ - 断言中的 dynamic_cast 导致错误