重新解释_cast
大多数时候,在 Delphi 中,演员表是reinterpret_cast
,即一种类型的位和字节被重新解释为另一种类型,例如Integer(myEnum)
or Pointer(MyDynamicArrayVar)
.
有些演员会剪掉一些位,即Integer(MyInt64)
将切断的前 32 位Int64
,低32位的最高位将成为新的符号位。有些演员阵容会扩大,例如Integer(myByte)
,尽管这种到更大类型的转换不需要强制转换。转换自,例如Integer
到浮点也不需要强制转换。
但有时它并不是一个reinterpret_cast
,并且强制转换会进行真正的转换(例如,从string
to PChar
如果字符串为空则转换;演员阵容来自AnsiString
to UTF8String
将内容转换为 UTF-8,并且UnicodeString(myAnsiChar)
甚至转换两次,从AnsiChar
to AnsiString
to UnicodeString
,尽管这些步骤可能并不全部可见)。有些类型转换是根本不允许的(例如Int64(MyDouble)
或某些尺寸不匹配的演员表)。
请注意,通过运算符重载(主要用于记录),您也可以进行显式和隐式转换。显式转换采用强制转换的形式。隐式转换也可以通过“强制转换”来强制。
Delphi 中强制转换的形式始终是typename(cast_object)
,这会投射cast_object
to typename
.
一些无效的强制转换可以使用指针来规避。如果你做类似的事情:
MyInt64 := PInt64(@MyDouble)^;
where PInt64
是一个指向Int64
其他类型是显而易见的,
然后你可以投一个Double
to an Int64
。注意没有完成实际的指针杂耍。转换是直接的,as if你已经做了
MyInt64 := Int64(MyDouble); // Invalid typecast -- except in some versions
没有多余的种类static_cast
在德尔福。我个人希望我们有像 C++ 中那样的显式强制转换。 Delphi 更像是 C 语言。
动态转换
如果涉及的类型是类或接口,则存在使用以下等价物as
and is
关键词。例如:
myEdit := MyTObject as TEdit;
myIntf := MyObj as ISomeInterface;
都是动态向上转型。与 C++ 不同,这些会引发(在 C++ 中抛出)EInvalidCast
异常如果MyTObject
不是一个实例TEdit
, or if myObj
不实施 ISomeInterface
。在其他方面它与 C++ 等效:
TEdit *myEdit = dynamic_cast<TEdit *>(MyTObject);
if (myEdit == NULL) throw ...
查询,就像经常做的那样dynamic_cast
在 C++ 中,可以用is
:
if MyObject is TEdit then
TEdit(MyObject).Text := 'Hello, world!';
这或多或少相当于 C++ 中的这种“模式”:
TEdit *e = dynamic_cast<TEdit *>(MyObject);
if (e != NULL)
e->Text = "Hello, world!";