C++ 将基类强制转换为派生类时,动态_强制转换失败

C++ 将基类强制转换为派生类时,动态_强制转换失败,c++,polymorphism,dynamic-cast,reinterpret-cast,C++,Polymorphism,Dynamic Cast,Reinterpret Cast,我有两个类,基类和派生类。 基类有一个虚方法 下面是我的测试示例: class Base { public: virtual void Hello() { cout << "-> Hello Base" << endl; } }; class Derived: public Base { public: void Hello() { cout << "-> Hello Derived" << endl; } }; i

我有两个类,基类和派生类。 基类有一个虚方法

下面是我的测试示例:

class Base
{
public:
    virtual void Hello() { cout << "-> Hello Base" << endl; }
};

class Derived: public Base
{
public:
    void Hello() { cout << "-> Hello Derived" << endl; }
};

int main()
{
    Base *mBase = new Base;
    // something to do 
    ....

    Derived *mDerived = dynamic_cast<Derived*>(mBase);
    mDerived->Hello();

    return 0;
}
案例中的结果
动态\u cast

Segmentation fault (core dumped)
-> Hello Base
将基类强制转换为派生类时,动态_强制转换失败

这是应该发生的事情。当您动态强制转换指向动态类型不是强制转换类型的对象的指针时,您会得到一个空指针作为结果

在您的示例中,您可以通过null指针间接调用一个成员函数,从而导致未定义的行为

使用动态强制转换时,必须始终检查是否为null

如果我使用reinterpret_cast

然后行为仍然是未定义的,因为您将通过指针间接指向不存在的对象。除非创建派生类的实例,否则不能调用其非静态成员函数

可以将基本实例转换为派生实例,例如:

Base b;
Derived d = b;

所发生的情况是,派生实例的基本子对象是从
b

复制初始化的,代码中有两个问题:
base
应该有一个虚拟析构函数,因此
Dervied
isntances可以通过指向
base
的指针正确析构函数。然后,您没有构造类型为
派生的
的对象,因此强制转换无法成功
dynamic_cast
可能会失败,您应该检查其结果是否为
nullptr
。您还忘记删除创建的对象

如果您确实创建了类型为
Derived
的实例,则您的代码可以工作:

#include <iostream>
using std::cout;
using std::endl;

class Base
{
public:
    virtual void Hello() { cout << "-> Hello Base" << endl; }
    virtual ~Base(){}
};

class Derived: public Base
{
public:
    void Hello() { cout << "-> Hello Derived" << endl; }
};

int main()
{
    Base* mBase = new Derived;
    Derived *mDerived = dynamic_cast<Derived*>(mBase);
    if (mDerived) mDerived->Hello();
    delete mBase;
}
#包括
使用std::cout;
使用std::endl;
阶级基础
{
公众:

virtual void Hello(){cout
Base*mBase=new Base;
应该是
Base*mBase=new-Derived;
您创建一个
Base
对象,并尝试将其强制转换为无法工作的
Derived
(mBase)
将返回空指针,因为
mbaase
不指向
Derived
对象的
Base
子对象,因此您取消引用无效指针。使用
reinterpret\u cast
返回的指针也将是未定义的行为,原因相同-
mbaase
不指向
Base
子对象
派生的
对象的对象。您希望强制转换更改对象的类型吗?不需要。虚拟析构函数不是多态类型所必需的,至少有一个虚拟方法或构造函数是多态类型。@Jean BaptisteYunès没有虚拟构造函数。虽然从技术上讲,类可能不需要虚拟构造函数orphic,虚拟析构函数对于
delete mBase;
具有良好定义的行为是绝对必要的。@Jean BaptisteYunès更改了措辞(并修复了泄漏)@eerorika将编写析构函数,抱歉。“虚拟析构函数是绝对必要的”不,当然不是。在大多数情况下是的,但也有一些情况是不必要的(比如考虑没有字段的类的层次结构)。我知道这是一个建议,但不是必要的。@Jean BaptisteYunès参见标准部分[expr.delete]