您已经用三种语言标记了这个问题,而这三种语言之间的答案确实有很大不同。对 C++ 的讨论或多或少也意味着对 C 强制转换的讨论,这或多或少给出了第四个答案。
由于这是您没有明确提到的,我将从 C 开始。C 强制转换有很多问题。一是他们可以做许多不同事情中的任何事情。在某些情况下,强制转换只是告诉编译器(本质上):“闭嘴,我知道我在做什么”——也就是说,它确保即使您进行可能导致问题的转换,编译器也会不会警告您这些潜在的问题。仅举个例子,char a=(char)123456;。定义的此实现的确切结果(取决于char),除非在相当奇怪的情况下,否则可能没有用。 C 类型转换还取决于它们是仅在编译时发生的事情(即,您只是告诉编译器如何解释/处理某些数据)还是在运行时发生的事情(例如,从 double 到 double 的实际转换)长的)。
C++ 试图通过添加许多“新”强制转换运算符来至少在某种程度上解决这个问题,每个运算符都仅限于 C 强制转换功能的一个子集。这使得(例如)意外地进行您实际上不打算进行的转换变得更加困难 - 如果您only想要放弃对象的常量,你可以使用const_cast,并确保only它可以影响的是一个对象是否是const, volatile, 或不。相反,一个static_cast不允许影响一个对象是否是const or volatile。简而言之,您拥有大多数相同类型的功能,但它们是经过分类的,因此一次强制转换通常只能执行一种转换,而单个 C 样式强制转换可以在一个操作中执行两种或三种转换。主要的例外是你can use a dynamic_cast代替一个static_cast至少在某些情况下,尽管被写成dynamic_cast,它最终会变成static_cast。例如,您可以使用dynamic_cast向上或向下遍历类层次结构 - 但层次结构“向上”转换始终是安全的,因此可以静态完成,而层次结构“向下”转换不一定安全,因此它是动态完成的。
Java 和 C# 彼此更加相似。特别是,对于它们来说,强制转换(实际上?)始终是运行时操作。就 C++ 强制转换运算符而言,它通常最接近dynamic_cast就真正完成的事情而言——即,当您尝试将对象转换为某种目标类型时,编译器会插入一个运行时检查以查看是否允许该转换,如果不允许,则抛出异常。确切的细节(例如,用于“错误转换”异常的名称)有所不同,但基本原理仍然基本相似(不过,如果没记错的话,Java 确实会将转换应用于少数非对象类型,例如int更接近于 C 类型转换——但这些类型很少被使用,以至于 1) 我不太记得这一点,2) 即使它是真的,也没关系)。