为什么要避免铸造?
我通常尽可能避免使用类型,因为我认为这是糟糕的编码习惯,可能会导致性能损失。
但是如果有人问我解释为什么那样,我可能会把他们看成是头灯上的鹿。
那么为什么/何时投射不好?
它是一般的Java,C#,C ++还是每个不同的运行时环境自己处理它?
欢迎使用任何语言的具体细节,例如为什么它在c ++中不好?
你用三种语言标记了这三种语言,答案在三者之间真的很不一样。 对C ++的讨论或多或少意味着对C剧组的讨论,并且(或多或少地)给出第四个答案。
由于这是你没有明确提到的那个,我将从C开始。C演员阵容有许多问题。 一个是他们可以做许多不同的事情。 在某些情况下,转换只会告诉编译器(本质上):“闭嘴,我知道我在做什么” - 即,它确保即使在执行可能导致问题的转换时,编译器不会警告你这些潜在的问题。 举个例子, char a=(char)123456;
。 这个实现的确切结果被定义了(取决于char
的大小和符号),除了在相当奇怪的情况下,可能没有用处。 C语言转换在它们是否只发生在编译时(例如,你只是告诉编译器如何解释/处理某些数据)或发生在运行时发生的事情上也会有所不同(例如,实际从双精度转换为长)。
C ++至少在某种程度上试图通过添加一些“新”转换运算符来处理这些运算符,每个运算符仅限于C语言转换能力的一个子集。 这使得更难以(例如)意外地做一个你真正不想要的转换 - 如果你只打算抛弃一个对象的const,你可以使用const_cast
,并确保它唯一可以影响的是无论对象是const
还是volatile
,或者不是。 相反, static_cast
不允许影响对象是const
还是volatile
。 总之,你拥有大部分相同类型的功能,但是它们被分类,因此一个演员一般只能进行一种转换,其中一个C风格演员可以在一次操作中进行两次或三次转换。 主要的例外是,至少在某些情况下,您可以使用dynamic_cast
代替static_cast
,尽管被编写为dynamic_cast
,但它最终会以static_cast
结尾。 例如,你可以使用dynamic_cast
来遍历一个类的层次结构 - 但是一个强制转换的层次结构总是安全的,所以它可以静态地完成,而一个强制转换的层次结构不一定是安全的。它是动态完成的。
Java和C#更加相似。 特别是,他们两个都是(几乎?)总是一个运行时操作。 就C ++类型转换运算符而言,它通常最接近dynamic_cast
,就实际完成情况而言 - 即,当您尝试将某个对象转换为某种目标类型时,编译器将插入运行时检查以查看该转换是否为允许,如果不是,则抛出异常。 确切的细节(例如,用于“不良转换”异常的名称)各不相同,但基本原则仍然大部分相似(尽管如果内存起作用,Java确实会将转换应用于少数几个非对象类型,如int
更接近于C强制转换 - 但这些类型的使用很少,以至于1)我不记得那是肯定的,2)即使它是真的,反正也没有关系)。
更一般地看待事物,情况非常简单(至少IMO):一个演员(显然是足够的)意味着你将某种类型的东西从一种类型转换为另一种类型。 当/如果你这样做,它会提出“为什么?”这个问题。 如果你真的想要某种特定的类型,为什么不把它定义为这种类型? 这并不是说没有任何理由去做这样的转换,但是只要发生这种转换,它就会提示您是否可以重新设计代码,以便始终使用正确的类型。 即使看起来无害的转换(例如整数和浮点之间的转换)也应该比普通转换得更密切。 尽管它们看似相似,但整数应该真正用于“计数”类型的事物和浮点“测量”类型的事物。 忽略这种区别就是导致一些疯狂的言论,比如“普通的美国家庭有1.8个孩子”。 尽管我们都可以看到这种情况,但事实是,没有一个家庭有1.8个孩子。 他们可能有1个,或者他们可能有2个,或者他们可能有更多 - 但从来没有1.8。
这里有很多好的答案。 这是我看待它的方式(从C#的角度来看)。
投射通常意味着两件事之一:
我知道这个表达式的运行时类型,但编译器不知道它。 编译器,我告诉你,在运行时对应于这个表达式的对象实际上将是这种类型的。 到目前为止,你知道这个表达式被视为这种类型。 生成假定对象是给定类型的代码,或者,如果我错了,则抛出异常。
编译器和开发人员都知道表达式的运行时类型。 还有另一个与此表达式在运行时所具有的值关联的不同类型的值。 生成从给定类型的值生成所需类型值的代码; 如果你不能这样做,那就抛出一个异常。
注意那些是相反的。 有两种演员! 有些地方你正在向编译器提供关于现实的暗示 - 嘿,这个类型对象的东西实际上是Customer类型的 - 并且有一些演员正在告诉编译器执行从一种类型到另一种类型的映射 - 嘿,我需要对应于这个double的int。
这两种演员都是红旗。 第一种投射引发了一个问题:“为什么开发人员知道编译器没有的东西?” 如果你处于这种情况,那么通常要改变程序,以便编译器确实掌握实际情况。 那么你不需要演员; 分析在编译时完成。
第二种类型提出了“为什么目标数据类型中的操作不是首先完成?” 如果你需要一个整数结果,那么你为什么要在第一个地方加倍? 你不应该持有一个int吗?
这里还有一些想法:
http://blogs.msdn.com/b/ericlippert/archive/tags/cast+operator/
在java中,铸造错误总是作为运行时错误报告。 使用泛型或模板将这些错误转化为编译时错误,使得在发现错误时更容易检测。
正如我上面所说。 这并不是说所有的铸造都不好。 但是,如果可以避免它,那么最好这样做。
链接地址: http://www.djcxy.com/p/21433.html上一篇: Why should casting be avoided?
下一篇: Using scanf() in C++ programs is faster than using cin?