У меня возникла небольшая проблема - я не знаю, смогу ли я определить собственные операторы для своих классов.
Например:
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 .NET возможна перегрузка оператора, более старые версии Delphi ее не поддерживают.
Перегрузка оператора, безусловно, возможна в Delphi Win32 2007 и новее для записей. Но не для занятий, это правильно.
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. Но конструктор копирования также может помочь.
«Традиционный» метод копирования классов в 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
Уточните, пожалуйста, Delphi для Win32 или для .NET? Какая версия Delphi?