【问题标题】:different behavior of static_cast and dynamic_cast in a specific scenariostatic_cast 和 dynamic_cast 在特定场景中的不同行为
【发布时间】:2018-02-06 08:17:44
【问题描述】:

我不明白下面场景中 static_cast 和 dynamic_cast 的真正区别:

                                **///with static_cast///**
    class Foo{};
    class Bar: public Foo
    {
        public:
          void func()
          {
            return;
          }
    };

    int main(int argc, char** argv)
    {
        Foo* f = new Foo;
        Bar* b = static_cast<Bar*>(f);
        b->func();
        return 0;
    }

输出:

编译成功!

                                **///with dynamic_cast///**
    class Foo{};
    class Bar: public Foo
    {
        public:
          void func()
          {
            return;
          }
    };

    int main(int argc, char** argv)
    {
        Foo* f = new Foo;
        Bar* b = dynamic_cast<Bar*>(f);
        b->func();
        return 0;
    }

输出:

main.cpp: 在函数'int main(int, char**)': main.cpp:26:34: 错误: 不能 dynamic_cast 'f'(类型为 'class Foo*')输入 'class Bar*' (源类型不是多态的) Bar* b = dynamic_cast(f);

如果有人能帮助我理解这一点,我将不胜感激!

【问题讨论】:

  • 当第一个构建和运行时,它会导致未定义的行为,因为f(因此b)不是指向Bar的指针对象。
  • 至于dynamic_castthis reference应该会有所帮助。
  • 您不能将指向基类对象的指针转换为派生类指针。 dynamic_cast(如果是虚拟成员)将返回 nullptrstatic_cast 将编译但使用此类指针将导致未定义的行为。
  • @DanielLangr 这种强制转换本身是未定义的行为。

标签: c++ oop inheritance dynamic-cast static-cast


【解决方案1】:

提示在部分

(源类型不是多态的)

这意味着,要让dynamic_cast 工作,它需要一个多态基类,即有一个虚方法

class Foo {
public:
    virtual ~Foo() {}
};

除此之外,它不会工作,因为f 不指向Bar 对象。 dynamic_cast 在这种情况下会返回一个 nullptr,你必须检查它

Foo* f = new Foo;
Bar* b = dynamic_cast<Bar*>(f);
if (b != nullptr)
    b->func();

【讨论】:

  • 只是稍微扩展一下:需要多态基类的主要原因是执行此运行时检查。一个较小的原因是启用对virtual 继承关系的向下转换。 static_cast 无法处理后一种情况,因为基类子对象的偏移量在派生类及其所有进一步派生类之间不固定。
猜你喜欢
  • 2011-01-16
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
  • 2010-11-18
  • 2014-05-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多