在 C++ 中使用 reinterpret_cast 进行向下转换

Pan*_*nch 1 c++ visual-c++ c++11

我只是想更详细地了解向下转换,我知道这是不可取的,因为它会导致未定义的运行时行为。我们什么时候真的需要使用向下转换?

还要考虑向下转换的编码片段和 dynamic_cast 返回,但是当我使用 reinterpret_cast 时,它正确地打印出派生类函数,如何?只有在按值分配对象而不是按引用或指针分配对象时,对象切片才会发生?

#include <iostream>
using namespace std;

class base
{
    public:
    void func1()
    {
        std::cout<<"\n Base Function"<<std::endl;
    }
    virtual ~base(){cout<<"\n Base Destructor"<<endl;}
};

class derived:public base
{
    public:
    void func2()
    {
        std::cout<<"\n Derived Function"<<std::endl;
    }
};

int main() 
{

    base *ptr = dynamic_cast<base*>(new derived); // Up casting
    if (ptr)
    {
        ptr->func1();
    }
    else
    {
        cout<<"\n casting failed"<<endl;
    }

    derived *ptr1 = dynamic_cast<derived*>(new base); // Down casting
    if (ptr1)
    {
        ptr1->func2();
    }
    else
    {
        cout<<"\n ptr1 casting failed"<<endl;
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

小智 6

向下转型本身不会导致未定义的行为。如果您有指向 base 的指针或引用,则可以使用 dynamic_cast 并确保它仅在它确实是派生的情况下才有效。如果它不是派生的,您将获得 nullptr 或异常(在转换引用时)。一切都将在运行时检查。

如果您已经知道您的基指针是派生的,则可以改用 static_cast。但是,不会执行任何检查,因此您可能会导致基指针的未定义行为不是派生的。

reinterpret_cast 不应用于向下转换。与 static_cast 一样,不会执行运行时检查,也不会执行编译时检查。您可能会意外地跨继承树进行转换(例如,从 base 到 other_base)。对于单继承的情况,reinterpret_cast 将像 static_cast 一样工作,但是当使用多重继承时,reinterpret_cast 不会修改指向对象内部正确基数的指针,并且您有未定义的行为。

当您可以使用 static_cast 时,我建议您远离 reinterpret_cast。