Dynamic_cast在三级继承的情况下会导致分段冲突

dynamic_cast causes segmentation violation in case of three level inheritance

本文关键字:情况下 冲突 分段 继承 三级 cast Dynamic      更新时间:2023-10-16

似乎dynamic_cast在三级继承的情况下不起作用。

应用程序在print()方法调用点(在main()中)由于分割错误(核心转储)而崩溃。

代码如下:

#include <iostream>
#include <typeinfo>     //must be included to call any member functions for the typeinfo object returned by typeid()
using namespace std;
class CBase
{
public:
    virtual void print()
    {
        cout<<"CBase::print"<<endl;
    }
    virtual ~CBase()
    { }
};
class CDerivedA : public CBase
{
public:
    virtual void print()
    {
        cout<<"CDerivedA::print"<<endl;
    }
    virtual ~CDerivedA()
    {}
};
class CDerivedB : public CDerivedA
{
public:
    void print()
    {
        cout<<"CDerivedB::print"<<endl;
    }
};
int main()
{
    CBase* ptrB = new CDerivedA();
    CDerivedB* ptrDB = dynamic_cast<CDerivedB*>(ptrB);
    ptrDB->print();
    return 1;
}

"指向CDerivedA的指针"(基类)不能强制转换为"指向CDerivedB的指针"(派生类)。注意,我不是指声明的指针类型;问题是指向的实际对象实际上是基类的一个实例,因此向下转换不能成功。

dynamic_cast在向下转换失败的情况下返回null指针,这可能是分割冲突的原因(在转换引用的情况下,它将抛出bad_cast异常)。

注意dynamic_cast需要RTTI(运行时类型信息)才能正常工作。出于性能原因,可以在编译器中关闭RTTI(因为如果启用RTTI,会在运行时引入一些开销)。请再次检查是否在编译器中启用了RTTI。

编辑:关于你最后的评论-

Downcasting基础知识

不能向下转换基类的实例。您可以向下转换声明为"指向基类的指针"的指针,该指针实际上指向派生类的实例。一个如何使用向下转换的例子:

class Base 
{ public:
  virtual void baseMethod() {cout<<"baseMethod in Base"<<endl;} 
  // I am omitting virtual destructors here for brevity, 
  // which you should _not_ do in your code! 
}
class Derived : public Base 
{ public:
  void baseMethod() {cout<<"baseMethod in Derived"<<endl;} 
  virtual void derivedMethod(){cout<<"derivedMethod in Derived"<<endl;} 
}
class Derived2 : public Derived 
{ public:
  void baseMethod() {cout<<"baseMethod in Derived2"<<endl;} 
  void derivedMethod(){cout<<"derivedMethod in Derived2"<<endl;} 
  void derived2Method(){cout<<"derived2Method in Derived2"<<endl;} 
} 
void someFunction(Base* pBase) 
{ 
  // pBase may actually point to an instance of Base, Derived or Derived2. 
  // But you can invoke only 'baseMethod' on pBase, 
  // since 'derivedMethod' and 'derived2Method' are not declared in Base. 
  pBase->baseMethod(); // ok
  // ERROR: pBase->derivedMethod(); 
  // ERROR: pBase->derived2Method(); 
  // To invoke 'derivedMethod', you have to downcast to Derived: 
  Derived* pDerived = dynamic_cast<Derived*>(pBase); 
  if(pDerived /* != null */) 
  { 
    // Downcast successful, i.e. 
    // pBase actually points to an instance of Derived _or_ Derived2. 
    // Both have the 'derivedMethod', so you can invoke it via 'pDerived' pointer: 
    pDerived->derivedMethod(); // ok 
    // ERROR: pDerived->derived2Method(); 
    // To call 'derived2Method', you have to downcast to Derived2. 
  } 
  else 
  { 
    // If we are here, then dynamic_cast returned null, 
    // i.e. the downcast was NOT successful 
    // and pBase actually points to an instance of Base. 
  } 
} 

避免投

你应该试着设计你的程序,这样就不需要强制类型转换了。使用多态性代替。在基类中声明所有需要的方法。使用纯虚方法。

将基类升级为派生类

不能通过强制转换升级实例。如果您想将Base的实例升级到Derived的实例,那么你必须在Derived中定义一个以Base为参数的构造函数,并通过new创建一个派生的新实例。注意,Base的旧实例保持原样,只创建了Derived的新实例。

class Derived : public Base 
{ public:
  Derived(Base& base) 
    : Base(base) // use copy constructor of Base 
  {
    // initializations specific to Derived
  } 
  // ... other methods ... 
}

// Usage: 
Base* pBase = new Base(); 
Derived* pDerived = new Derived(*pBase); // "upgrade" Base to Derived. 
// The instance of Base (pointed to by pBase) still lives, 
// and a new instance of Derived (pointed to by pDerived) is born. 
// Do not forget to delete both pBase and pDerived! 

我希望这对你有帮助。

非常感谢Tadeusz Kopec的更正。