在具有相同基类的派生类之间进行dynamic_cast时会发生什么?

时间:2018-05-30 11:12:52

标签: c++11 polymorphism dynamic-cast static-cast

我试图弄清楚当你从一个派生类dynamic_cast到另一个派生类时会发生什么。为什么以下代码会引发分段错误?请注意,我不是试图将此代码用于任何事情。我只是想了解发生了什么。

同样值得注意的是,相同的代码使用static_cast。我似乎无法找到任何有关这里发生的细节的详细文档。有人可以解释一下吗?

struct base 
{ 
    virtual void printing(){cout<<"base printing"<<endl;};
};
struct derived_1 :public base 
{ 
    virtual void printing(){cout<<"derived_1 printing"<<endl;};
};
struct derived_2 :public base 
{ 
    virtual void printing(){cout<<"derived_2 printing"<<endl;};
};

int main()
{
    base * b = new derived_2();
    derived_1 *d_1 = dynamic_cast<derived_1*>(b);

    // calling printing raises segmentation fault
    d_1->printing(); 
}

1 个答案:

答案 0 :(得分:1)

转换为derived_1会失败,因为derived_2 base对象,但 derived_1宾语。因此,您不能“侧转”到所需的指针类型。

不是每当dynamic_cast失败时,它都会返回nullptrexcept for reference types)。这最终导致代码中的分段错误(通常,我建议您在使用动态转换对象之前始终添加if (d_1 != nullptr)。)

<强>更新

顺便说一句,这实际上是dynamic_cast必要性的一个很好的例子。即使你可能想在你的例子中使用static_cast并且它会编译,你将处理未定义的行为。使用static_cast将编译没有hickups,但你实际上将使用一个破碎的类型。假设derived_1::printing()访问derived_1::a中不存在的变量derived_2。通过静态地将derived_2对象(没有a)转换为derived_1对象d_1,您会错误地认为d_1包含一些有效a,情况并非如此。

示例:

// ...
struct derived_1 :public base
{
    const int a = 123;
    void printing() override {cout<<"derived_1 printing " << endl;}
    void foo() { cout << "Foo using constant = " << a << endl; }
};

// ...
int main()
{
    base * b = new derived_2();
    derived_1 *d_1 = static_cast<derived_1*>(b);
    d_1->printing(); // Will call derived_2::printing(), which is not what you expect!
    d_1->foo();      // Won't show a = 123 but some nonesense (mostly 0),
                     // because a is not defined in derived_2.
}