[More Effective C++]尽量使用C++风格的类型转换

Item M2:尽量使用C++风格的类型转换

1、C不支持以下转换:

1)把一个指向const 对象的指针(pointer-to-const-object)转换成指向const 对象的指针(pointer-to-non-const-object);

2)把一个指向基类的指针转换成指向子类的指针;

2、C++通过引进四个新的类型转换操作符克服了C 风格类型转换的缺点,这四个操作符是:

1)  static_cast;

2)  const_cast

3)dynamic_cast

4)   reinterpret_cast

2.1 static_cast

我们熟悉的强制转化格式为:(type) expression

现在可以这样写:static_cast<type>(expression)

例如: int firstNumber,secondNumber;

             double result =((double)firstNumber)/secondNumber;

如果用上述新的类型转换方法,你应该这样写:

            doubleresult = static_cast<double>(firstNumber)/secondNumber;

static_cast限制:

1)  你不能用static_cast把struct 转换成int 类型或者把double 类型转换成指针类型;

2)  static_cast 不能从表达式中去除const 属性,但是另一个新的类型转换操作符const_cast 有这样的功能。

2.2 const_cast

    const_cast 用于类型转换掉表达式的const 或volatileness属性,如果你试图使用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 最普通的用途就是转换掉对象的const 属性;

2.3 dynamic_cast

它被用于安全地沿着类的继承关系向下进行类型转换。

你能用dynamic_cast 把指向基类的指针或引用转换成指向其派生类或其兄弟类的指针或引用;失败的转换将返回空指针(当对指针进行类型转换时)或者抛出异常(当对引用进行类型转换时)。

Widget *pw;
update(dynamic_cast<SpecialWidget*>(pw));
// 正确,如果pw 确实指向一个对象,传递给update函数一个指针
// 是指向变量类型为SpecialWidget 的pw 的指针
//否则传递过去的将使空指针。
voidupdateViaRef(SpecialWidget& rsw);
updateViaRef(dynamic_cast<SpecialWidget&>(*pw));
//正确。如果pw确实指向了某个对象传递给updateViaRef 函数SpecialWidget pw 指针,否则将抛出异常.

dynamic_casts 的限制;

    它不能被用于缺乏虚函数的类型上,也不能用它来转换掉constness;

如你想在没有继承关系的类型中进行转换,你可能想到 static_cast。如果是为了去除const,你必须用const_cast,当需要继承关系的转换时你要用dynamic_casts。

2.4 reinterpret_cast

    使用这个操作符的类型转换,其的转换结果几乎都是执行期定义(implementation-defined)。因此,使用reinterpret_casts的代码很难移植。

reinterpret_casts 的最普通的用途就是在函数指针类型之间进行转换。例如,假设你有一个函数指针数组:

typedef void (*FuncPtr)(); //FuncPtr is 一个指向函数
// 的指针,该函数没有参数
// 返回值类型为void
FuncPtr funcPtrArray[10]; //funcPtrArray 是一个能容纳
// 10 个FuncPtrs 指针的数组
int doSomething();
funcPtrArray[0] = &doSomething; // 错误!类型不匹配
reinterpret_cast 可以让你迫使编译器以你的方法去看待它们:
funcPtrArray[0] = // this compiles
reinterpret_cast<FuncPtr>(&doSomething);

    如果你使用的编译器缺乏对新的类型转换方式的支持,你可以用传统的类型转换方法代替static_cast, const_cast, 以及reinterpret_cast。也可以用下面的宏替换来模拟新的类型转换语法,其中的限制要注意:

#definestatic_cast(TYPE,EXPR) ((TYPE)(EXPR))
#defineconst_cast(TYPE,EXPR) ((TYPE)(EXPR))
#definereinterpret_cast(TYPE,EXPR) ((TYPE)(EXPR))
#definedynamic_cast(TYPE,EXPR) (TYPE)(EXPR)

你可以象这样使用使用:

double result = static_cast(double,firstNumber)/secondNumber;
update(const_cast(SpecialWidget*, &sw));
funcPtrArray[0] = reinterpret_cast(FuncPtr,&doSomething);


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值