reinterpret_cast
Большую часть времени в Delphi приведение является reinterpret_cast
, то есть биты и байты одного типа переинтерпретируются, как если бы это был другой тип, например Integer(myEnum)
или Pointer(MyDynamicArrayVar)
.
Некоторые броски обрезают биты, т. Е. Integer(MyInt64)
обрезает верхние 32 бита Int64
, а верхний бит младших 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.
dynamic_cast
Если задействованы типы классов или интерфейсов, то есть эквиваленты, использующие ключевые слова as
и is
.Например:
myEdit := MyTObject as TEdit;
myIntf := MyObj as ISomeInterface;
оба динамических повышения.В отличие от C ++, они вызовут (сгенерирует в C ++) исключение EInvalidCast
, если MyTObject
не является экземпляром TEdit
или если 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!";