类型转换
-
隐式类型转换
-
数值类型转换
-
指针类型转换
- 空指针可以转换到任意指针类型
- 任意指针类型都可以转换到 void* 指针
- 继承类指针可以转换到可访问的明确的基类指针,同时不改变const 或者 volatil 属性
- 一个C风格的数组隐式把数组的第一个元素转换为一个指针。 虽然此方法很方便,但它也有潜在的错误。 例如,下面的设计不良的代码示例看似荒谬,但它会在Visual C++的编译并生成的结果’p’。 首先,“Help”字符串常量转换为一个指向数组的第一个元素 char*类型指针,该指针向后移动3个元素后,指向最后一个元素’P’
-
显示类型转换
旧有的 C 风格的强制类型转换是不推荐的;因为在代码中不显眼,容易被忽略,而且旧式强制转换实际上是困难且容易出错的。
explicit
关键字
C++ 提供了关键字explicit
, 可以阻止不应该允许的经过转换构造函数进行的隐式转换的发生。即声明为explicit
的构造函数不能在隐式转换中使用。- 强制类型转换
-
static_cast<new_type>(expression)
static_cast
强制转换只会在编译时检查,但没有运行时类型检查来保证转换的安全性。同时,static_cast
也不能去掉expression
的const
、volatile
、或者__unaligned
属性。
其主要应用场景有:- 用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类指针或引用)时,由于没有动态类型检查,所以是不安全的。
- 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
- 把
void
指针转换成目标类型的指针(不安全!!!) - 把任何类型的表达式转换成
void
类型 - 将
enum class
值转化为 整数或者浮点数 - 转换为右值引用
-
dynamic_cast<new_type>(expression)
new_type
必须是一个指针或引用或“指向void
的指针”。 如果new_type
是指针,则expression
的类型必须是指针,如果type-id
是引用,则expression
为左值。 如果转型失败会返回null
(转型对象为指针时)或抛出异常(转型对象为引用时)。dynamic_cast
会动用运行时信息(RTTI
)来进行类型安全检查,因此dynamic_cast
存在一定的效率损失
dynamic_cast
的一个重要作用就是要确保转换结果应该指向一个完整的目标类型。下面给一个示例:#include <iostream> #include <exception> using namespace std; class Base { virtual void dummy() {} }; class Derived: public Base { int a; }; int main () { try {Base * pba = new Derived;Base * pbb = new Base;Derived * pd;pd = dynamic_cast<Derived*>(pba); if (pd==0) cout << "Null pointer on first type-cast.\n"; pd = dynamic_cast<Derived*>(pbb); if (pd==0) cout << "Null pointer on second type-cast.\n";} catch (exception& e) {cout << "Exception: " << e.what();} return 0; }
分析:分析: 尽管pba和pbb都是Base指针类型,但其指向的对象却分别是Derived 和 Base。而由于Base相比Derived少了int a的定义,因此无法完整的由Base转到Derived。
此外,dynamic_cast只有在基类存在虚函数(虚函数表)的情况下才有可能将基类指针转化为子类。 -
const_cast<new_type>(expression)
new_type
必须是一个指针、引用或者指向对象类型成员的指针。
const_cast
用于去除对象的const
或者volatile
属性。void Func(double& d) { ... } void ConstCast() { const double pi = 3.14; Func(const_cast<double&>(pi)); //No error. }
-
reinterpret_cast<new_type>(expression)
new_type
必须是一个指针、引用、算术类型、函数指针或者成员指针。其转换结果与编译平台息息相关,不具有可移植性,因此在一般的代码中不常见到它。reinterpret_cast
常用的一个用途是转换函数指针类型,即可以将一种类型的函数指针转换为另一种类型的函数指针,但这种转换可能会导致不正确的结果。总之,reinterpret_cast
只用于底层代码,一般我们都用不到它,如果你的代码中使用到这种转型,务必明白自己在干什么
-