【发布时间】:2019-03-09 22:10:58
【问题描述】:
在 Delphi 中,什么是 C++ 的 dynamic_cast、reinterpret_cast 和 static_cast 运算符(尤其是用于对象时)?
【问题讨论】:
标签: c++ delphi c++builder
在 Delphi 中,什么是 C++ 的 dynamic_cast、reinterpret_cast 和 static_cast 运算符(尤其是用于对象时)?
【问题讨论】:
标签: c++ delphi c++builder
大多数时候,在 Delphi 中,强制转换是 reinterpret_cast,即一种类型的位和字节被重新解释为另一种类型,例如Integer(myEnum) 或 Pointer(MyDynamicArrayVar)。
一些强制转换会截断位,即Integer(MyInt64) 将截断Int64 的前32 位,而低32 位的高位将成为新的符号位。一些演员表扩展,例如Integer(myByte),尽管此类转换为更大的类型不需要强制转换。转换,例如Integer 到浮点数也不需要强制转换。
但有时它不是reinterpret_cast,并且转换进行了真正的转换(例如,如果字符串为空,则从string 转换为PChar;从AnsiString 转换为UTF8String 转换将内容转换为 UTF-8,UnicodeString(myAnsiChar) 甚至会转换两次,从 AnsiChar 到 AnsiString 到 UnicodeString,尽管这些步骤可能并非全部可见)。并且某些演员表根本不允许(例如Int64(MyDouble) 或某些尺寸不匹配的演员表)。
请注意,使用运算符重载(主要用于记录),您也可以进行显式和隐式转换。显式转换采用强制转换的形式。隐式转换也可以通过“强制转换”来强制。
Delphi 中的转换形式始终为typename(cast_object),将cast_object 转换为typename。
一些无效的转换可以使用指针来规避。如果您执行以下操作:
MyInt64 := PInt64(@MyDouble)^;
其中PInt64 是指向Int64 的指针,其他类型很明显,
然后您可以将Double 转换为Int64。请注意,没有进行实际的指针处理。转换是直接的,就像你已经完成了
MyInt64 := Int64(MyDouble); // Invalid typecast -- except in some versions
Delphi 中没有额外的static_cast。我个人希望我们有像 C++ 那样的显式转换。 Delphi 更像是 C 语言。
如果所涉及的类型是类或接口,则使用 as 和 is 关键字可以实现等价。例如:
myEdit := MyTObject as TEdit;
myIntf := MyObj as ISomeInterface;
两种动态向上转换。与 C++ 不同,如果MyTObject 不是TEdit 的实例,或者myObj 没有实现 ISomeInterface,这些将引发(在C++ 中抛出)EInvalidCast 异常。它在其他方面等同于 C++:
TEdit *myEdit = dynamic_cast<TEdit *>(MyTObject);
if (myEdit == NULL) throw ...
查询,就像 C++ 中经常使用 dynamic_cast 完成的一样,可以使用 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!";
【讨论】:
dynamic_cast 有一个直接等价物 - the is and as operators。 if obj is T then 等价于if (dynamic_cast<T*>(obj) != NULL) 而obj as T 等价于T* pT = dynamic_cast<T*>(obj); if (pT == NULL) throw ...;
&dynamic_cast<T&>(*ptr)
myEdit := TEdit(MyTObject) 类似于 static_cast 但用于对象。