Могу ли я перегружать операторы для моих собственных классов в Delphi?

У меня возникла небольшая проблема - я не знаю, смогу ли я определить собственные операторы для своих классов. Например:

type
  TMinMatrix = class(TMatrix)
    private
      RowAmount: Byte;
      ColAmount: Byte;
      Data: DataMatrix;
      DemVector, SupVector: SupplyDemand;
    public
      constructor Create(Rows, Cols: Byte);
      function GetRowAmount: Byte; override;
      function GetColAmount: Byte; override;
      destructor Destroy;
  end;

Как я могу - или не могу :) - сделать что-то вроде:

TMinMatrix TMinMatrix::operator=(TMinMatrix* matr)    (c++ code)

И, кстати, могу ли я определить конструктор копирования для своего класса?

Уточните, пожалуйста, Delphi для Win32 или для .NET? Какая версия Delphi?

gabr 01.12.2008 00:15
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
4 240
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Ответ принят как подходящий

В версиях Delphi .NET возможна перегрузка оператора, более старые версии Delphi ее не поддерживают.

Перегрузка оператора, безусловно, возможна в Delphi Win32 2007 и новее для записей. Но не для занятий, это правильно.

gabr 01.12.2008 10:01

Delphi Win32 2007 и 2009 поддерживает только перегрузку операторов класса для записей, вы можете иметь неявные и явные операторы. Delphi .Net поддерживает операторы классов для записей и классов.

Что бы ни говорили Дрейк и Сезар, Delphi Win32 2007 и 2009 не поддерживают конструкторы копирования, насколько мне известно (я на 100% поддерживаю D2007, не совсем уверен в D2009).

Я полагаю, что конструктор копирования - это идиома, а не языковая функция. Так что я могу это сделать так:
конструктор CreateCopy (var t: MyType);

конструктор MyType.CreateCopy (var t: MyType);
begin
//...
конец;

Delphi больше любит использовать Assign. Но конструктор копирования также может помочь.

Toon Krijthe 02.12.2008 02:17

«Традиционный» метод копирования классов в Delphi - это переопределение метода «AssignTo» TPersistant. Обычно это принимает форму

TSubclass(Dest).Field1 := Field1;
TSubclass(Dest).Field2 := Field2;

Что немного больно.

конструктор CreateCopy затем вызовет этот метод:

constructor CreateCopy(ASource : TMyClass);
begin
  Create;
  Assign(ASource); // calls AssignTo
end;

еще одна уловка в более поздних (работает в 2006 году) версиях Delphi - использовать тип записи для хранения полей.

class TMyClass = class(TPersistent)
protected
  type  // 2005+ only, otherwise use standalone record
    TMyRecord = record
    Name : string;
    ID : integer;
  end;

  FData : TMyRecord;
  procedure AssignTo(Dest : TPersistent);override;
public
  property Name : string read FData.Name;
  property ID: Integer read FData.ID;
end;

procedure TMyClass.AssignTo(Dest : TPersistent);
begin
  if Dest is TMyClass then
     TMyClass(Dest).FData := FData
  else
    inherited; // raise EConvertError
end;

Это становится беспорядочным, если вы продолжаете добавлять поля в подклассы - нужно добавлять новые типы записей, но он автоматически обрабатывает новые поля, добавленные в TMyrecord (не нужно помнить об обновлении AssignTo ())

type
  TMinMatrix = class(TMatrix)
    public
      A : integer;
      class operator Add( ATM, BTM : TMinMatrix ) : TMinMatrix;
          // CTM := ATM + BTM
      class operator Subtract( ATM, BTM : TMinMatrix ) : TMinMatrix;
          // CTM := ATM - BTM;
    end;

class operator TMinMatrix.Add( ATM, BTM : TMinMatrix ) : TMinMatrix;
  begin
    result := ATM.A + BTM.A;
  end;

class operator TMinMatrix.Subtract( ATM, BTM : TMinMatrix ) : TMinMatrix;
  begin
    result := ATM.A - BTM.A;
  end;


var
  A, B, C : TMinMatrix;
begin
  C := A + B;  // calls Add()
  C := B - A;  // calls Subtract()
end.

Другие операторы:

Add        Binary   Add(a: type; b: type): resultType;         +   
Subtract   Binary   Subtract(a: type; b: type) : resultType;   -   
Multiply   Binary   Multiply(a: type; b: type) : resultType;   *   
Divide     Binary   Divide(a: type; b: type) : resultType;     /
IntDivide  Binary   IntDivide(a: type; b: type): resultType;   div   
Modulus    Binary   Modulus(a: type; b: type): resultType;     mod   
LeftShift  Binary   LeftShift(a: type; b: type): resultType;   shl   
RightShift Binary   RightShift(a: type; b: type): resultType;  shr   
LogicalAnd Binary   LogicalAnd(a: type; b: type): resultType;  and   
LogicalOr  Binary   LogicalOr(a: type; b: type): resultType;   or   
LogicalXor Binary   LogicalXor(a: type; b: type): resultType;  xor   
BitwiseAnd Binary   BitwiseAnd(a: type; b: type): resultType;  and   
BitwiseOr  Binary   BitwiseOr(a: type; b: type): resultType;   or   
BitwiseXor Binary   BitwiseXor(a: type; b: type): resultType;  xor   

;)

Перегрузка операторов в Delphi Win32 работает только для записей, а не для классов.

Он работает с Delphi 2006 и выше, но в Delphi 2007 были исправлены некоторые ошибки, которые упрощают работу с ними (связанные с вызовом функций для результатов оператора).

Я проводил сессию по перегрузке оператора записи на CodeRage 3; Вы можете получить слайды и образец кода на 26326 CR3: Обнуляемые типы с записями, методами и перегрузкой оператора и / или посмотреть видеоповтор на СКАЧАТЬ ВИДЕОПОВТОР.

Это была аннотация сеанса:

Nullable Types with Records, Methods and Operator Overloading One of the things where data from databases and Delphi native types differ, is the support for NULL. When you work with databases a lot in Delphi, you want to have a datatype that supports NULL. In the past you had to use variants, but not any more! With the introduction of operator overloading, you can do this with record types, too. This session shows you how.

Причина, по которой перегрузка оператора возможна только для записей в Delphi Win32 (т.е. не .NET), заключается в том, что записи являются типами значений, поэтому их управление памятью не является динамическим. Классы являются ссылочными типами, поэтому для них требуется динамическое выделение памяти: им требуется концепция сборщика мусора, чтобы операторы могли с ними работать.

Поскольку в Delphi Win32 нет концепции сборщика мусора, в Delphi Win32 невозможно использовать операторы для классов.

Обратите внимание, что CodeRage 4 начинается на следующей неделе. У него хороший состав докладчиков и сессий.

Delphi позволяет перегружать определенные функции или операторы в объявлениях записей. Вы можете увидеть здесь: http://edn.embarcadero.com/article/34324

Другие вопросы по теме