Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the equivalent of dynamic_cast in Delphi?

In Delphi, what is the equivalent of C++'s dynamic_cast, reinterpret_cast, and static_cast operators (especially when used on objects)?

like image 775
Server Overflow Avatar asked Oct 04 '18 13:10

Server Overflow


People also ask

Is Dynamic_cast a code smell?

Yes, dynamic_cast is a code smell, but so is adding functions that try to make it look like you have a good polymorphic interface but are actually equal to a dynamic_cast i.e. stuff like can_put_on_board .

Is Static_cast faster than Dynamic_cast?

While typeid + static_cast is faster than dynamic_cast , not having to switch on the runtime type of the object is faster than any of them.

Is Dynamic_cast fast?

dynamic_cast runs at about 14.4953 nanoseconds. Checking a virtual method and static_cast ing runs at about twice the speed, 6.55936 nanoseconds.

What is dynamic cast in CPP?

In C++, dynamic casting is, primarily, used to safely downcast; i.e., cast a base class pointer (or reference) to a derived class pointer (or reference). It can also be used for upcasting; i.e., casting a derived class pointer (or reference) to a base class pointer (or reference).


1 Answers

reinterpret_cast

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. Integer(myEnum) or Pointer(MyDynamicArrayVar).

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 string to PChar converts if the string is empty; a cast from AnsiString to UTF8String converts the contents to UTF-8, and UnicodeString(myAnsiChar) converts even twice, from AnsiChar to AnsiString to 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 cast_object to typename.

Some invalid casts can be circumvented using pointers. If you do something like:

MyInt64 := PInt64(@MyDouble)^;

where 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.

dynamic_cast

If the types involved are classes or interfaces, then there are equivalents using the as and 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 is:

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!";
like image 50
Rudy Velthuis Avatar answered Oct 23 '22 23:10

Rudy Velthuis