In Delphi, what is the equivalent of C++'s
static_cast operators (especially when used on objects)?
Most of the time, in Delphi, a cast is a
reinterpret_cast, i.e. the bits and bytes of one type are reinterpreted as if it were another type, e.g.
Some casts cut off bits, i.e.
Integer(MyInt64) will cut off the top 32 bits of the
Int64, and the top bit of the lower 32 bits will become the new sign bit. Some casts expand, e.g.
Integer(myByte), although such conversions to a larger type don't require a cast. Conversions from, e.g.
Integer to floating point don't require casts either.
But sometimes it is not a
reinterpret_cast, and the cast does a real conversion (e.g. a cast from
PChar converts if the string is empty; a cast from
UTF8String converts the contents to UTF-8, and
UnicodeString(myAnsiChar) converts even twice, from
UnicodeString, although these steps may not all be visible). And some casts are simply not allowed (e.g.
Int64(MyDouble) or certain casts where the sizes don't match).
Note that with operator overloading (mainly for records), you can have explicit and implicit conversions too. The explicit conversions take the form of a cast. The implicit conversions can be forced by "casting" too.
The form of a cast in Delphi is always
typename(cast_object), which casts
Some invalid casts can be circumvented using pointers. If you do something like:
MyInt64 := PInt64(@MyDouble)^;
PInt64 is a pointer to
Int64 and the other types are obvious,
then you can cast a
Double to an
Int64. Note that no actual pointer juggling is done. The conversion is direct, as if you had done
MyInt64 := Int64(MyDouble); // Invalid typecast -- except in some versions
There is no extra kind of
static_cast in Delphi. I personally wish we had such explicit casts like in C++. Delphi's are more like in C.
If the types involved are classes or interfaces, then there are equivalents using the
is keywords. For example:
myEdit := MyTObject as TEdit; myIntf := MyObj as ISomeInterface;
both dynamic upcasts. Unlike in C++, these will raise (throw in C++) an
EInvalidCast exception if
MyTObject is not an instance of
TEdit, or if
myObj doesn't implement
ISomeInterface. It is otherwise equivalent to C++:
TEdit *myEdit = dynamic_cast<TEdit *>(MyTObject); if (myEdit == NULL) throw ...
Querying, like often done with
dynamic_cast in C++, can be done with
if MyObject is TEdit then TEdit(MyObject).Text := 'Hello, world!';
That is more or less equivalent to this "pattern" in C++:
TEdit *e = dynamic_cast<TEdit *>(MyObject); if (e != NULL) e->Text = "Hello, world!";