计算机编程/类型转换
在计算机科学中,类型转换或类型强制转换是指将一个数据类型的值转换为另一个数据类型。转换有两种类型:隐式和显式。隐式类型转换被称为强制转换。显式类型转换以某种特定方式被称为强制转换。显式类型转换也可以通过单独定义的转换例程来实现,例如重载的类构造函数。
隐式类型转换,也称为强制转换,是由编译器自动完成的类型转换。一些语言允许甚至要求编译器提供强制转换。
在混合类型表达式中,一个子类型s将被转换为一个超类型t,或一些子类型s1、s2、... 将被转换为一个超类型t(可能没有si是类型t),在运行时,以确保程序能够正确运行。例如
double d;
long l;
int i;
if (d > i) d = i;
if (i > l) l = i;
if (d == l) d *= 2;
在C语言程序中是合法的。虽然d、l和i属于不同的数据类型,但在每次执行比较或赋值时,它们将被自动转换为相同的数据类型。
显式转换有几种类型。
- 检查式
- 在执行转换之前,会进行运行时检查以查看目标类型是否能够实际容纳源值。如果不能,则会引发错误条件。
- 非检查式
- 不会执行任何检查,如果目标类型不能容纳源值,则结果将是未定义的。
- 位模式
- 数据不会被解释,只会复制原始位模式。
每种编程语言都有自己的规则来规定如何转换类型。通常,对象和基本数据类型都可以被转换。
强制转换,或显式类型转换,是一种特殊的编程指令,它指定在给定表达式中将变量(或中间计算结果)视为哪种数据类型。
强制转换将忽略“额外”的信息(但永远不会向被转换的类型添加信息)。C/C++强制转换是“非检查式”或“位模式”。
以基本数据类型为例,一个定点浮点数可以被强制转换为一个整数,其中小数点(或二进制点)后的数据将被忽略。或者,一个整数可以被强制转换为一个浮点数,例如,如果一个函数调用需要一个浮点类型(但如前所述,实际上不会添加任何信息,1 将变成 1.0000000)。
对象强制转换的工作方式类似。一个子类可以被强制转换为一个父类型,其中使它成为子类的“额外”信息将被忽略,只处理从父类继承的部分。例如,从形状类派生的三角形类可以被强制转换为形状。
有两种常见的转换方式,如下所示。
这种转换方式在C和Java中使用。它遵循以下形式
(type)expression
在C++中使用了多种转换语法(虽然也支持C风格转换)。函数调用风格遵循以下形式
type(expression)
这种转换方式被采用是为了在使用转换时强制清晰。例如,C风格转换的
(type)firstVariable + secondVariable
的结果和意图可能不清楚,而使用C++风格转换的相同转换可以使意图更加清晰
type(firstVariable + secondVariable)
或
type(firstVariable) + secondVariable
在C++的演变过程中,为了进一步明确程序员的意图,添加了以下更明确的转换方式
static_cast<type>(value_to_cast)
dynamic_cast<type>(value_to_cast)
const_cast<type>(value_to_cast)reinterpret_cast<type>(value_to_cast)
静态转换将类型兼容的值进行转换。例如,以下示例
double myDouble = 3.0;
int myInt = static_cast<int>(myDouble);
将双精度浮点数值myDouble
(3.0)转换为相应的整数值(3)。静态转换可能很危险
YourClass * pYour = GimmeAnObject();
void * pv = pYour; // no cast needed.
MyClass * p = static_cast<MyClass *>(pYour); // MyClass had better be related to YourClass...
p->SomeMethod(); // ...or this might blow up in a nasty way.
对指针或引用的静态转换不会验证指向的对象是否与新类型兼容。
在这种情况下,动态转换比静态转换更安全:它由编译器编译成对C++运行时库的调用,在那里会进行检查以确保转换合法。这类似于Java中的转换。
YourClass * pYour = GimmeAnObject();
void * pv = pYour; // no cast needed.
MyClass * p = dynamic_cast<MyClass *>(pYour); // This will not blow up in the same way
if (p != 0)
p->SomeMethod(); // C++ guarantees p points to a MyClass
对指针的动态转换如果转换值类型不兼容,则返回空指针。对引用的动态转换会抛出一个类型异常。
const转换将消除对象的const属性,返回对同一对象的非const引用。这允许对通常由编译器视为只读的对象进行修改
const MyClass * cantTouchThis = CreateConstObject();
cantTouchThis->constant_value = 41; // compile-time error.
const_cast<MyClass *>(cantTouchThis)->constant_value = 42; // compiles, but who knows what happens at runtime?
重新解释转换是C++中最臭名昭著的一个。它允许重新解释值的原始位模式,完全忽略类型系统。例如,它允许将任意整数强制转换为指向对象的指针
MyClass * pclass = reinterpret_cast<MyClass *>(0xDEADBEEF); // I know what I am doing
pclass->some_field = 3.14159; // very unsafe indeed
//Using Converting of Type casting
Console.WriteLine("\nUsing Converting of Type casting"); string U = "10000000"; int V = Convert.ToInt32(U);
Console.WriteLine("\nHinger value={0} and Lower value ={1}", U, V);
当这些冗长的转换被引入到语言中时,意见分歧。反对者认为新的语法很“丑”,而支持者认为,由于转换本身就是一个“丑陋”的活动,所以应该用一个“丑陋”的语法来突出显示它,以提醒程序员。另一个被认为的优势是,使用像grep这样的编程工具,很容易在源代码中找到冗长的转换。