深入static_cast运算符
深入static_cast运算符
2011年03月29日
学无止境,把这几年收藏的文章都晒出来,大家共享吧! 声明:早期转载的文章未标明转载敬请原谅,以后将陆续改过来,向原创者致敬! C++ , Direct3D, OpenGL, GPU,OGRE,OSG,STL, Lua, Python, MFC, Win32 (有问题可留言,部分网页看不到图片可网页另存为到本地再打开即可看到) 痞子龙3D编程 QQ技术交流群:32103634
本文下载地址:
http://bbs.sjtu.edu.cn/file/Apple/1200681928238350 .pdf
许可:
http://creativecommons.org/licenses/by-nc-nd/2.5/c n
作者:Robert Schmidt
Microsoft Corporation
2000年5月18日
译者:高博
http://www.gaobo.org
[email protected]
依我数年在Usenet的C++新闻组的潜水经验来看,四个型别转换运算符:const_cast、dy
namic_cast、reinterpret_cast和static_cast之间究竟关系如何一直是软件工程师的困
扰之源。尤其是reinterpret_cast和static_cast的区别,对许多软件工程师而言十分模
糊--或者不如说简直是视而不见。在以下的两讲里,我会演示一下两者之间的区别,
并给出何时应该应用何者的指南。(译注:本文是讲了static_cast的第一讲。)
概览
顾名思义,static_casts将具有某种静态型别的表达式转换成具有另外某种静态型别的
对象或值。如C++标准(§2.5.9/1-3)(译注:原文误写为5.2.9)所言:
表达式static_cast(v)之结果就是将表达式v转换为型别T的结果。如果T是一个引用
型别,则结果为一个左值。否则,结果是一个右值。在一个static_cast表达式内不可定
义新的型别。static_cast运算符不会将表达式的常量性(constness)转换掉。
……
能够显式地使用形如"static_cast(e)"的static_cast表达式来转换为型别T的表达
式e必须满足:"T t(e);"对某个虚构的临时变量t是一个合式的声明。否则,static_c
ast表达式将执行下面列出的转换之一:
……
其它任何的型别转换都不能够显式地通过使用static_cast来实现。
这就是说,允许使用static_cast的场合包括:
.一个具有目标型别(转换后的型别)的对象能够直接以一个具有源型别(转换前的型
别)的值来初始化,或者
.此种转换符合某个标准§2.5.9中随后列举的例外情形之一(我随后会简要地一一说明
之)。
标准的§2.5.9还提及,static_cast运算符"不会将表达式的常量性转换掉"。标准实
际是说static_cast不会卸除CV-饰词(译注:即常量性--constness,饰词const和挥
发性--volatility,饰词volatile)。比如,static_cast运算符不可以把char
const *转换为char *,尽管它可以把char *转换为char const *。(如果你想要卸除CV
-饰词的话,唯一合用的型别转换运算是const_cast。我会在下面的一个更广义的讨论"
常量正确性"--const correctness的论文里作有关const_cast运算符的完整论述,此
去略去不提。)
例:
现有声明:
struct B{
operator int();
};
struct D : B{
};
B b;
float const f = 0;
下面的型别转换:
static_cast(&b); // 等价于"(void *) &b;"
static_cast(b); // 等价于"(int) b;"和"int(b);"
都是合式的。第一个型别转换依赖于一个标准支持的从B *到void *的隐式型别转换,而
第二个则隐式调用了b.operator int()。两个型别转换都遵从了标准§2.5.9中描述的一
般规则。但正如我刚才提到的,它还列出了一些一般规则不能涵盖的例外。这些例外使
得以下的转换加入了被允许之列:
static_cast(f); // 等价于"(int) f;"和"int(f);"
static_cast(b); // 等价于"(D &) b;"
尽管这些转换的目标型别对象是不能用源型别的值来初始化的。
最后,看看这对表达式:
static_cast(&f); // 没问题
static_cast(&f); // 错误!
第一个转换成功完成了,但第二个可耻地失败了。它们都企图把一个指涉到float的指针
转换成一个指涉到int的指针,但是第二个转换把const饰词也转换掉了--这是标准大
声禁止的。第二个转换如果在老旧的型别转换语法里就能够畅行无阻:
(int *) &f; // 译注:没问题
隐式型别转换
标准的§2.5.9/1允许:
T t = static_cast(e);
当:
T t(e);
是合式的,亦即,直接的、无转型的初始化是可行的。这隐含了一层意思,就是声明:
long l = static_cast('x');
和
long l('x');
是等价的。你也许会对语言居然允许这样冗余的转型觉得古里古怪,就好像它们仅仅使
源代码显得更加
猜你喜欢
转载自shv283fi.iteye.com/blog/1361807
今日推荐
周排行