Can I overload operators for my own classes in Delphi?

I faced a little trouble - I do not know if I can define my own operators for my classes. For example:

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;

How can I - or can`t I:) - do something like:

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

And, by the way, can I define copy constructor for my class?

Answers


Operator overloading is possible in Delphi .NET versions, older versions of Delphi don't support it.


Delphi Win32 2007 and 2009 only supports class operator overload for records, you can have implicit and explicit operators. Delphi .Net supports class operators for records and classes.


The "traditional" method of copying classes in Delphi is by overriding the "AssignTo" method of TPersistant. This usually takes the form of

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

Which is a bit of a pain.

a CreateCopy constructor would then call this method:

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

another trick in later (works in 2006) versions of Delphi is to use an record type to store the fields.

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;

This gets messy if you keep adding fields in sub-classes - need to add new record types, but it automatically handles new fields added into TMyrecord (don't have to remember to update 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.

Other operators are:

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   

;)


Whatever Drejc and Cesar said + Delphi Win32 2007 and 2009 don't support copy constructors as far as I know (I'm 100% for D2007, not totally sure for D2009).


Operator overloading in Delphi Win32 works only for records, not for classes.

It works from Delphi 2006 and up, but there were some bugs fixed in Delphi 2007 that make them easier to work with (having to do with calling functions on operator results).

I gave a session on Record Operator Overloading on CodeRage 3; You can get the slides and sample code at 26326 CR3: Nullable Types w/ Records, Methods & Operator Overloading, and/or watch the video replay at DOWNLOAD VIDEO REPLAY.

This was the session abstract:

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.

The reason operator overloading is only possible for records in Delphi Win32 (i.e. non .NET), is that records are value types, so their memory management is non-dynamic. Classes are reference types, hence require dynamic memory allocation: they require the concept of a garbage collector in order for operators to work on them.

Since there is no concept of a garbage collector in Delphi Win32, it is not possible in to have operators for classes in Delphi Win32.

Note that CodeRage 4 starts next week. It has a nice line up of speakers and sessions.


I suppose copy constructor is an idiom, not a language feature. So I can do it like this: constructor CreateCopy(var t: MyType);

constructor MyType.CreateCopy(var t: MyType); begin //... end;


Delphi allows certain functions, or operators, to be overloaded within record declarations. You can see here: http://edn.embarcadero.com/article/34324


Need Your Help

How to have Query Pull Weekly Data

sql sql-server tsql

I have a a query like so that ONLY shows data for the specific day. But how can I modify this to show data for the previous 7 days? So when I run the query this week show data for the date range o...

Modern alternative to DELETE ... WHERE ... NOT IN (...)?

sql-server tsql sql-server-2012

Taking the following two table variables, is there any (faster/shorter/more efficient) alternative to delete any data from @tbl_big that doesn't exist within @tbl_small? The reason is that I have a