ReadingLab / Discussion-for-Cpp

C++ 中文讨论区
MIT License
89 stars 63 forks source link

dynamic_cast的一个疑问 #72

Closed ender233 closed 7 years ago

ender233 commented 7 years ago

参考手册中对dynamic_cast执行失败给出了两个结果:

  1. 如果目标类型是指针,那么结果就是一个空指针
  2. 如果目标类型是个引用,那么就抛异常

    If the cast fails and new_type is a pointer type, it returns a null pointer of that type. If the cast fails and new_type is a reference type, it throws an exception that matches a handler of type std::bad_cast.

但是为啥如下代码,虽然会失败,但是也没有返回空指针,直接coredump了呢?

class Widget {
public:
    virtual ~Widget(){}
};
class SpecialWideget {
public:
    virtual ~SpecialWideget(){}
}

Widget *pw;
// Widget *pw = new SpecialWideget()   // ok基类指针实际指向子类
SpecialWideget * pw2 = dynamic_cast<SpecialWideget *>(pw);
pezy commented 7 years ago

http://coliru.stacked-crooked.com/a/9871ec5b531b6791

并不会 coredump 啊, 我在 vs2015 上也试过了。请问你是什么编译环境?

另外,Widget* pw; 这句看着很不舒服, 最好初始化一下。 Widget* pw = nullptr;

ender233 commented 7 years ago

看来是和编译环境有关, 在这个编译器上构造了一下,这是必core的 http://coliru.stacked-crooked.com/a/fe0d95ee00850215

可能问题就是出在了没有初始化,编译器有时把未初始化指针置成nullptr, 有时候给定了地址,后一种情况调用dynamic_cast的时候就挂了.

至于编译器赋值规则,就不纠结了;
dynamic_cas转失败后 除了空指针和异常 还有coredump. 不过都是运行时的错误coredump和异常倒也没啥本质区别.

代码来自<More effective c++>,第几个item忘了. 回家看看. 我抄错了或者书里面就是没赋值.

pezy commented 7 years ago

有时候给定了地址,后一种情况调用dynamic_cast的时候就挂了.

是的,这完全取决于编译器,好的习惯是,定义的时候就直接初始化,这样保证在各种平台上编译时,行为保持一致。

代码来自<More effective c++>,第几个item忘了

应该是 item2 吧,这本书最新一次出版都是 2005 年了,连 C++11 都没出来。那时候各种编译器神奇优化掩盖了很多标准上未涉及的问题。所以用现在的眼光去看,没有初始化为 nullptr,应该是疏漏无疑。

在 VS 2015 上,如果对 pw 不初始化,默认会直接编译报错。

ender233 commented 7 years ago

clear 感谢.