dynamic_cast和多态性

dynamic_cast and polymorphism

本文关键字:多态性 cast dynamic      更新时间:2023-10-16

这是我在这个网站上的第一个问题,所以请随时强调我的单词选择、问题结构等方面的任何问题。

最近,我开始在处理多态性时使用dynamic_cast,我读到dynamic_cast不会创建类的另一个实例,而是创建指向对象的指针的另一个实例。

在测试dynamic_cast时,我遇到了这个问题。这是代码:

//main.cpp
#include <iostream>
class Base{
public:
    int BaseNum;
    virtual void BaseFunction(){};
};
class Derived : public Base{
public:
    int DerivedNum; 
    virtual void DerivedFunction(){};
};
int main(){
    Base * ptrBase = new Base;
    ptrBase->BaseNum = 0;
    Derived * ptrDerived = dynamic_cast<Derived *>(ptrBase);
    ptrDerived->DerivedNum = 1;
    std::cout << ptrBase->BaseNum << ptrDerived->DerivedNum << std::endl;
    system("pause");
    return 0;
}

程序在行中崩溃:

ptrDerived->DerivedNum = 1;

调试时,它说"无法读取内存"。我的结论是,如果原始内存分配是为层次结构中较高的类保留的,我不能失望,但我认为我可能是错的。

代码哪里出了问题?

dynamic_cast

指定的对象中查找请求的类类型,并返回指向对象该部分的指针/引用。如果找不到,则为指针转换返回 NULL,并为引用转换引发std::bad_cast异常。在您的示例中,它失败是因为ptrBase没有指向作为 Derived 类实例的对象,因此对象中没有要返回指针的Derived节,因此它返回 NULL。 您需要更改此设置:

Base * ptrBase = new Base;

对此:

Base * ptrBase = new Derived;

您的问题是您正在向后使用动态投射。

如果你这样做了

   Base *ptrBase = new Derived ;

然后它就会起作用。

派生的 IS 一个基数。基础不是派生的。

在示例代码中,创建 Base 的新实例:

Base * ptrBase = new Base;
ptrBase->BaseNum = 0;
Derived * ptrDerived = dynamic_cast<Derived *>(ptrBase);

因为DerivedBase的超集,但基只是Derived的一个子集,你不能把ptrBase指向的对象寻址为Derived,因为它比Derived"小"。

另一方面,如果你写

Base * ptrBase = new Derived;
ptrBase->BaseNum = 0;
Derived * ptrDerived = dynamic_cast<Derived *>(ptrBase);

那么一切都很好,因为现在ptrBase指向的对象是Derived.

对于dynamic_cast,程序员有责任确保转换成功。