MEC | 条款2 最好使用C++转型操作符

条款2 最好使用C++转型操作符

MEC | 条款2 最好使用C++转型操作符_第1张图片

文章目录

  • 条款2 最好使用C++转型操作符
    • c++4个转型操作符
      • static_cast
      • const_cast
      • dynamic_cast
      • reinterpret_cast
    • 宏模仿新转换语法
      • 欢迎关注公众号【三戒纪元】

c++4个转型操作符

  • static_cast
  • const_cast
  • dynamic_cast
  • reinterpret_cast

原因是

  1. 新式转型方法容易便是出来,而且一眼能看出来是想做什么类型转换。
  2. 编译器得以判断转型错误(旧式转型无法做到)

static_cast

要从C的旧事转型,改为新的转型方法

(type) expression

==>

static_cast<type> (expression)

static_cast 拥有与C旧事转型相同的威力和意义,以及相同的限制。

const_cast

const_cast 用来改变表达式中的常量性(constness)或易变性(volatileness)

class Widget { ... };
 
class SpecialWidget : public Widget{ ... };

void update(SpecialWidget* psw) {}

SpecialWidget sw; // sw是一个非const对象
const SpecialWidget& csw = sw; // csw是sw的一个引用,它是一个const对象
update(&csw); // 错误,不能传递一个const SpecialWidget*变量给一个处理SpecialWidget*类型变量的函数
update(const_cast<SpecialWidget*>(&csw)); // 正确,csw的const显示地转换掉(csw和sw两个变量值在update函数中能被更新)
update((SpecialWidget*)&csw); // 同上,但用了一个更难识别的C风格的类型转换
 
Widget* pw = new SpecialWidget;
update(pw); // 错误,pw的类型是Widget*,但是update函数处理的是SpecialWidget*类型
update(const_cast<SpecialWidget*>(pw)); // 错误,const_cast仅能被用在影响constness or volatileness的地方,不能用在向继承子类进行类型转换

显然,const_cast 最常见的用途就是将某个对象的常量性去除掉

dynamic_cast

用来执行继承体系中的“安全向下转型或跨系转型动作”。

具体有2个作用:

  1. 将指向 base class objects的pointers 或 references 转型为 指向 derived(或sibling base) class objects 的 pointers 或 references,并得知转型是否成功。转型失败会返回 null 指针或 1个 expression
  2. 找出某个对象占用的内存的起始点
class Widget { ... };
 
class SpecialWidget : public Widget{ ... };

void update(SpecialWidget* psw) {}
void updateViaRef(SpecialWidget& rsw) {}

Widget* pw2 = nullptr;
update(dynamic_cast<SpecialWidget*>(pw2)); // 正确,传递给update函数一个指针是指向变量类型为SpecialWidget的pw2的指针, 
                                           // 如果pw2确实指向一个对象,否则传递过去的将是空指针
 
Widget* pw3 = new SpecialWidget;
updateViaRef(dynamic_cast<SpecialWidget&>(*pw3)); // 正确,传递给updateViaRef函数SpecailWidget pw3指针,
                                                  // 如果pw3确实指向了某个对象,否则将抛出异常
 
double result3 = dynamic_cast<double>(firstNumber) / secondNumber; // 错误,没有继承关系
const SpecialWidget sw4;
update(dynamic_cast<SpecialWidget*>(&sw4)); // 错误,dynamic_cast不能转换掉const

dynamic_cast 只能用来协助你巡航于继承体系中。

reinterpret_cast

这个操作符的转换结果几乎总是与编译平台息息相关,所以 reinterpret_cast 不具有移植性。

reinterpret_cast 最常用的用途是转换“函数指针”类型

比如想将一下函数的一个指针放进 funcPtrArray 中

type void (*FuncPtr); // FuncPtr 是个指针,指向某个函数
                      // 该函数无需任何自变量,返回值为void
FuncPtr funcPtrArray[10]; // funcPtrArray 是个数组,内有10个 FuncPtrs

int doSth();

funcPtrArray 内各函数指针所指函数的返回值为void,但 doSth 的返回值却是 int:

funcPtrArray[0] = &doSomething; // 错误,类型不匹配
funcPtrArray[0] = reinterpret_cast<FuncPtr>(&doSomething); // 编译通过

转换函数指针的代码是不可移植的, C++不保证所有的函数指针都被用一样的方法表示,在一些情况下这样的转换会产生不正确的结果,所以应该避免转换函数指针类型

宏模仿新转换语法

如果编译器不支持新式转型动作,使用宏可达到同样效果

#define static_cast(TYPE, EXPR) ((TYPE)(EXPR))
#define CONST_cast(TYPE, EXPR) ((TYPE)(EXPR))
#define  reinterpret_cast(TYPE, EXPR) ((TYPE)(EXPR))

宏方法不能保证转换安全,而且不能得知是否转换成功。


欢迎关注公众号【三戒纪元】

你可能感兴趣的:(c++)