明确C 风格的类型转换的用法
2008-02-23 05:24:59来源:互联网 阅读 ()
但是C风格的类型转换并不代表任何的类型转换功能。
一来他们过于粗鲁,能允许您在任何类型之间进行转换。但是假如要进行更精确的类型转换,这会是个长处。在这些类型转换中存在着巨大的不同,例如把一个指向const对象的指针(pointer-to-const-object)转换成指向非const对象的指针(pointer-to-non-const-object)(即一个仅仅去除const的类型转换),把一个指向基类的指针转换成指向子类的指针(即完全改变对象类型)。传统的C风格的类型转换不对上述两种转换进行区分。(这一点也不令人惊讶,因为C风格的类型转换是为C语言设计的,而不是为C 语言设计的)。
二来C风格的类型转换在程式语句中难以识别。在语法上,类型转换由圆括号和标识符组成,而这些能够用在C++中的任何地方。这使得回答象这样一个最基本的有关类型转换的问题变得很困难:“在这个程式中是否使用了类型转换?”。这是因为人工阅读很可能忽略了类型转换的语句,而利用象grep的工具程式也不能从语句构成上区分出他们来。
C 通过引进四个新的类型转换操作符克服了C风格类型转换的缺点,这四个操作符是, static_cast, const_cast, dynamic_cast, 和reinterpret_cast。在大多数情况下,对于这些操作符您只需要知道原来您习惯于这样写,
(type) expression |
而现在您总应该这样写:
static_cast<type>(expression) |
例如,假设您想把一个int转换成double,以便让包含int类型变量的表达式产生出浮点数值的结果。假如用C风格的类型转换,您能这样写:
int firstNumber, secondNumber; ... double result = ((double)firstNumber)/secondNumber; |
假如用上述新的类型转换方法,您应该这样写:
double result = static_cast<double>(firstNumber)/secondNumber; |
这样的类型转换不论是对人工还是对程式都很容易识别。
static_cast在功能上基本上和C风格的类型转换相同强大,含义也相同。他也有功能上限制。例如,您不能用static_cast象用C风格的类型转换相同把struct转换成int类型或把double类型转换成指针类型,另外,static_cast不能从表达式中去除const属性,因为另一个新的类型转换操作符const_cast有这样的功能。
其他新的C 类型转换操作符被用在需要更多限制的地方。const_cast用于类型转换掉表达式的const或volatileness属性。通过使用const_cast,您向人们和编译器强调您通过类型转换想做的只是改变一些东西的constness或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属性。
第二种特别的类型转换符是dynamic_cast,他被用于安全地沿着类的继承关系向下进行类型转换。这就是说,您能用dynamic_cast把指向基类的指针或引用转换成指向其派生类或其兄弟类的指针或引用,而且您能知道转换是否成功。失败的转换将返回空指针(当对指针进行类型转换时)或抛出异常(当对引用进行类型转换时):
Widget *pw; ... update(dynamic_cast<SpecialWidget*>(pw)); // 正确,传递给update函数一个指针 // 是指向变量类型为SpecialWidget的pw的指针 // 假如pw确实指向一个对象, // 否则传递过去的将使空指针。 void updateViaRef(SpecialWidget& rsw); updateViaRef(dynamic_cast<SpecialWidget&>(*pw)); //正确。传递给updateViaRef函数 // SpecialWidget pw 指针,假如pw // 确实指向了某个对象 // 否则将抛出异常 dynamic_casts在帮助您浏览继承层次上是有限制的。他不能被用于缺乏虚函数的类型上(参见条款M24),也不能用他来转换掉constness: int firstNumber, secondNumber; ... double result = dynamic_cast<double>(firstNumber)/secondNumber; // 错误!没有继承关系 const SpecialWidget sw; ... update(dynamic_cast<SpecialWidget*>(&sw)); // 错误! dynamic_cast不能转换 // 掉const。 |