为什么要避免铸造?[已关闭]
我通常尽可能避免转换类型,因为我的印象是这是糟糕的编码实践,可能会造成性能损失。
但是,如果有人让我解释为什么会这样,我可能会像在车灯下看一只鹿一样看着他们。
那么为什么/什么时候铸造不好呢?
它是java,c#,c ++的通用方法,还是每个不同的运行时环境都按照自己的条件处理它?
欢迎任何语言的细节,例如为什么它在c ++中不好?
我通常尽可能避免转换类型,因为我的印象是这是糟糕的编码实践,可能会造成性能损失。
但是,如果有人让我解释为什么会这样,我可能会像在车灯下看一只鹿一样看着他们。
那么为什么/什么时候铸造不好呢?
它是java,c#,c ++的通用方法,还是每个不同的运行时环境都按照自己的条件处理它?
欢迎任何语言的细节,例如为什么它在c ++中不好?
你已经用三种语言标记了这一点,这三种语言的答案确实大不相同。对C++的讨论或多或少也意味着对C转换的讨论,这给出了(或多或少)第四个答案。
由于这是你没有明确提到的那个,我将从C开始,C演员表有很多问题。一个是他们可以做许多不同事情中的任何一件。在某些情况下,强制转换只不过是告诉编译器(本质上是):“闭嘴,我知道我在做什么” - 也就是说,它确保即使你做了可能导致问题的转换,编译器也不会警告你这些潜在的问题。例如,.定义此实现的确切结果(取决于 的大小和符号),除非在相当奇怪的情况下,否则可能没有用。C转换在它们是仅在编译时发生的事情(即,您只是告诉编译器如何解释/处理某些数据)还是在运行时发生的事情(例如,从双倍到长整时的实际转换)方面也有所不同。char a=(char)123456;
char
C++试图通过添加一些“新”强制转换运算符来至少在某种程度上解决这个问题,每个运算符都仅限于C转换功能的子集。这使得(例如)意外地执行您真正无意的转换变得更加困难 - 如果您只打算丢弃对象的恒定性,则可以使用,并确保它唯一可以影响的是对象是否是 ,,或不是。相反,不允许 a 影响对象是 还是 。简而言之,您拥有大多数相同类型的功能,但它们被分类为一个转换通常只能执行一种转换,其中单个C样式转换可以在一个操作中执行两到三个转换。主要的例外是,至少在某些情况下,您可以使用 a 代替 a,尽管它被写成 a,但它最终会最终成为 .例如,您可以使用向上或向下遍历类层次结构 - 但是“向上”的层次结构始终是安全的,因此可以静态地完成,而“向下”的层次结构不一定是安全的,因此它是动态完成的。const_cast
const
volatile
static_cast
const
volatile
dynamic_cast
static_cast
dynamic_cast
static_cast
dynamic_cast
Java和C#彼此更相似。特别是,对于它们,强制转换(实际上?)始终是运行时操作。就C++强制转换运算符而言,就实际操作而言,它通常最接近于 - 即,当您尝试将对象强制转换为某种目标类型时,编译器会插入运行时检查以查看是否允许该转换,如果不允许,则引发异常。确切的细节(例如,用于“坏强制转换”例外的名称)各不相同,但基本原则仍然大致相似(但是,如果内存可用,Java确实将强制转换应用于少数非对象类型,例如更接近C转换 - 但这些类型很少使用,以至于1)我不确定,2)即使它是真的, 反正没有多大关系)。dynamic_cast
int
更广泛地看,情况非常简单(至少是IMO):演员(显然足够了)意味着你正在将某些东西从一种类型转换为另一种类型。当你/如果你这样做,它会提出一个问题“为什么?如果你真的希望某物是一种特定的类型,你为什么不把它定义为一开始就是那种类型呢?这并不是说永远没有理由进行这样的转换,但是每当它发生时,它都应该提示您是否可以重新设计代码以便在整个过程中使用正确的类型。即使是看似无害的转换(例如,整数和浮点之间的转换)也应该比通常的更仔细地检查。尽管它们看起来很相似,但整数确实应该用于“计数”类型的事物,浮点数用于“测量”类型的事物。忽视这种区别会导致一些疯狂的说法,比如“美国家庭平均有1.8个孩子”。尽管我们都可以看到这种情况是如何发生的,但事实是,没有一个家庭有1.8个孩子。他们可能有1个,或者他们可能有2个,或者他们可能有更多 - 但从来没有1.8。
这里有很多好的答案。以下是我看待它的方式(从C#的角度来看)。
铸造通常意味着以下两件事之一:
我知道这个表达式的运行时类型,但编译器不知道它。编译器,我告诉你,在运行时,与此表达式对应的对象实际上将属于此类型。截至目前,您知道此表达式将被视为此类型。生成假定对象属于给定类型的代码,或者,如果我错了,则引发异常。
编译器和开发人员都知道表达式的运行时类型。还有另一个不同类型的值与此表达式在运行时将具有的值相关联。生成从给定类型的值生成所需类型的值的代码;如果无法执行此操作,则引发异常。
请注意,这些是相反的。有两种施法!有些强制转换,你向编译器提供有关现实的提示 - 嘿,这个类型对象的东西实际上是客户类型 - 并且有强制转换,你告诉编译器从一种类型到另一种类型执行映射 - 嘿,我需要对应于这个双精度的int。
这两种投射都是危险信号。第一种强制转换提出了一个问题:“为什么开发人员知道编译器不知道的东西?如果您处于这种情况,那么更好的办法通常是更改程序,以便编译器确实能够处理现实。那么你就不需要演员阵容了。分析在编译时完成。
第二种强制转换提出了一个问题:“为什么一开始就不在目标数据类型中执行操作?如果你需要一个ints的结果,那么你为什么一开始就持有双打呢?你不应该拿着一个int吗?
这里有一些额外的想法: