读书笔记《Effective C++》条款27:尽量少做转型动作

C语言风格的旧式转型动作有两种形式:

(T)expression        //将expression转型为T
T(expression)        //将expression转型为T
两种形式并无差别。

C++还提供四种新式转型:

const_cast<T>(expression)
dynamic_cast<T>(expression)
reinterpret_cast<T>(expression)
static_cast<T>(expression)
各有不同的目的:

1.const_cast通常被用来将对象的常量属性移除(cast away the constness)。它也是唯一有此能力的C++ style转型操作符。

2.dynamic_cast主要用来执行“安全向下转型”(safe downcasting),也就是用来决定某对象是否归属继承体系中的某个类型。它是唯一无法由旧式语法执行的动作,也是唯一可能耗费重大运行成本的转型动作。

3.reinterpret_cast意图执行低级转型,实际动作(及结果)可能取决于编译器,这也就表示它不可移植。例如将一个pointer to int转型为一个int。这一类转型在低阶代码以外很少见。

4.static_cast用来强迫隐士转换(implicit conversions),例如将non-const对象转为const对象,或将int转为double等等。它也可以用来执行上述多种转换的反向转换,例如将void*指针转为typed指针,将pointer-to-base转为pointer-to-derived。但它无法将const转为non-const——这个只有const——cast才办得到。

C语言风格的旧式转型任然合法,但是新式转型较受欢迎。原因:第一,它们很容易在代码中被辨识出来(不论是人工辨识或使用工具如grep),因而得以简化“找出类型系统中哪个地点被破坏”的过程。第二,各转型动作的目标愈窄化,编译器愈可能诊断出错误的运用。比如,如果打算将constness去掉,除非使用新式转型中的const_cast否则无法通过编译。

之所以需要dynamic_cast,通常是因为你想在一个你认定为derived class对象身上执行derived class操作函数,但你的手上却只有一个“指向base”的pointer或reference,你只能靠它们来处理对象。有两个一般性做法可以避免这个问题。

第一,使用容器并在其中存储直接指向derived class对象的指针(通常是智能指针),如此便消除了“通过base class接口处理对象”的需要。

另一种做法可让你通过base class接口处理“所有可能之各种Window派生类”,那就是在base class内提供virtual函数做你想对各个Window派生类做的事。

dynamic_cast的许多实现版本执行速度相当慢。深度继承或多重继承的成本更高!

优良的C++代码很少使用转型,但若说要完全摆脱它们又太过于不切实际。


要点:

1.如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_cast。如果有个设计需要转型动作,试着发展无需转型的替代设计。

2.如果转型是必要的,试着将它隐藏于某个函数背后。客户随后可以调用该函数,而不需要将转型放进他们自己的代码中。

3.宁可使用C++style(新式)转型,不要使用旧式转型。前者很容易辨识出来,而且也比较有着分门别类的职掌。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值