要点

  • 表达式合法性和语义由操作数类型决定

  • 如果两个类型之间可以转换,则称这两类型相关

  • C++类型转换目标是尽可能防止精度丢失

隐式类型转换

优点

  • 方便开发人员的使用,避免各种显式地转换

  • 提供自然的语义,像内置类型一样,int(1) + double(1.1)

  • 无需额外重载,来支持多种操作符运算,重载数量与运算符线性相关!

缺点

  • 不利于掌控,有些隐式转换不是想要的,出现错误时,很难定位

发生场景

当某个变量需要T2类型值,而该表达式值为T1类型,此时编译器会执行隐式类型转换。

具体场景:

  1. 当该表达式作为某个操作符(=, +…)的操作数,与期望类型T2不符

  2. 当该表达式作为函数调用实参,与形参类型T2不符

  3. 当作为函数返回语句时,与返回类型T2不符

  4. 当该表达式作为switch语句(T2为intergal)

  5. 当该表达式作为条件表达式(if, while, for, !, &&, ||)(T2为bool)

实现方式(自定义类型)

T2=>T1

单参数构造函数(converting constructor)

1
2
T1(T2 t2);
T1(T2 t2, int i=0);

T1=>T2

类型转换操作符函数(Conversion Operator)

1
2
operator T2&();
operator T2() const;

# 禁止隐式类型转换

通过explicit关键字修饰函数,说明该函数不能被用来隐式转换,只能进行显式转换!

要点

  • 条件表达式中有singed和’unsigned’时,singed会转化为unsinged(对应类型的模运算值,如1B的-1转换为255)

显式类型转换(C++风格转换)

优点:

  1. 意图更加明确,编译器可以提供更准确地检查,尽可能早地发现错误

  2. 利于代码阅读和工具检索

static_cast

  • 编译期内

  • 使用隐式类型转换或用户自定义转换

  • 安全性较高,编译器进行类型检查

用途:

  • 相关类型的转换,如整型到枚举,浮点到整型

  • 显式转换,即使造成精度丢失,编译器也不会警告

  • void*的双向转换

reinterpret_cast

  • 编译期内

  • 不做任何检查的转换,保证再次转换回来时,值不变(前提是转换的类型有足够的空间存储原有值)

  • 危险性最高,完全靠程序员掌握

  • 不生成任何CPU指令,对编译器而言,直接把该值作为指定类型(变量的属性)操作

用途:

  • 主要用于不相关类型间转换,如整型到指针,不同指针类型间
1
2
int i = 1;
char *pch = reinterpret_cast<char *>(&i); // static_cast无法完成

const_cast

添加或移除constvolatile修饰

  • 不生成任何CPU指令,对编译器而言,本身这个修饰只是一种存取权限控制

dynamic_cast

  • 运行期内转换

  • 提供类型安全检查,可以知道转换是否成功

  • 最耗时

用途:

在同一个继承体系(带有虚函数表的)中进行类型转换

  • 子类向基类的向上转型(Up Cast)

  • 基类向子类的向下转型(Down Cast)

  • 横向转型(Cross Cast)

参考

  1. C++ Primer 5.12
  2. C++程序设计语言 6.2.7
  3. http://en.cppreference.com/w/cpp/language/implicit_conversion
  4. http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used?rq=1
  5. http://en.cppreference.com/w/cpp/language/reinterpret_cast

留言

2016-02-27