C++-style Type Conversion
优先使用 C++ 风格类型转换
大多数程序员都认为 C++ 是在 C 的基础上引入面向对象概念。这一观点并不完全准确。C 语言是一中简洁优雅的语言,若仅仅引入面向对象概念,由怎么会有众多编写 C++ 的大师认为自己对 C++ 的了解并不深呢?可想而知,C++ 比单纯的 “C 语言 + 面向对象” 还要更复杂得多。
C++ 在设计的时候同样也考虑到程序设计过程中的类型转换问题,但C语言风格的类型转换对于 C++ 来说过于简单粗暴(通过括号及目标类型来进行转换)。试想想,C 中只有基本数据类型以及用户自定义的 struct 结构,因此这样“简单粗暴”的类型转换对C来说是足够,但对引入面向对象之后的 C++ 却不然,至少 C++ 还有着无数程序员自定义的类。因此 C++ 也拥有自己的类型转换操作符。
除了上面所说的原因,还有另一个优先使用C++ 风格类型转换操作符的原因是 C 风格的类型转换不利于程序员或查找工具查找,人工查找本身就比较容易出错,而使用查找工具查找又如何?一个稍微大一些的程序,总会有许许多多的括号出现,要准确地定位到程序代码中何处使用了类型转换,恐怕使用查找工具也难以查找。
C++ 一共提供了四种类型转换操作符:
- static_cast<type>(expression);
- const_cast<type>(expression);
- dynamic_cast<type>(expression);
- reinterpret_cast<type>(expression);
C 风格是这么写: (type) expression; .从今起,C++ 应该这么写: static_cast<type> (expression);
这样的写法无论从人工审查或者是查找工具查找都更便于前者。
下面对C++ 提供的四种类型转换做一些介绍:
static_cast 操作符的功能和 C 语言的类型转换功能一样,而且有着同样的功能局限,例如不能将 struct 类型转换成 int 类型,等等。同时 static_cast 操作符也不能去除变量的 const 属性。范例代码:
和 C 风格类型转换不同的饿时, static_cast 不能移除类型的 const 属性。 const_cast 操作符,正好弥补了移除 const 属性这一问题。 const_cast 能够换掉类型的 const 和 volatileness 属性。从下面的代码,可以看出 const_cast 的用法
这里的 update(&csw) 是错误的,因为 update 参数是不带 const 属性; update(const_cast<SpecialWidget*>(&csw)); 使用了 C++ 风格类型转换,换掉了 csw 的 const 属性; update((SpecialWidget*) &csw); 使用了 C 语言风格的类型转换,同样换掉了 csw 的 const 属性。 const_cast 操作符只能用在影响 constness 或 volatilness 地方上,不能永在向继承子类进行类型转换,所以以下的语句也是错误的。
第三种类型转换是 dynamic_cast 操作符。 dynamic_cast 是用于安全地沿着类的继承关系向下进行类型转换。这也就是说 dynamic_cast 可以把指向基类的指针或引用转换为指向其派生类的指针或引用。
使用 dynamic_cast 进行类型转换的同时还可以知道转换是否成功,转换失败的时候,返回空指针或者抛出异常(指针转换失败返回空指针,引用转换失败抛出异常)。
但 dynamic_cast 类型转换是有限制的,它不能被用在缺乏虚函数的类型上。以下是 dynamic_cast 的例子:
最后一种类型转换是 reinterpret_cast 操作符。这个操作符在不同编译器环境有不同的实现,并且转换结果几乎是在运行期定义的,所以代码不利于移植,在此不做讨论。
小结
- 使用 C++ 风格类型转换的好处:安全,便于查找。
- 普通类型转换使用 static_cast 。
- 移除const 和 valatileness 属性可以使用 const_cast 。
- 在同一继承树上的类向下(向基类)转换使用 dynamic_cast 。
- 使用 reinterpret_cast需谨慎。