views:

1681

answers:

8

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?

+3  A: 

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

Drejc
Operator overloading is certainly possible in Delphi Win32 2007 and newer *for records*. But not for classes, that's correct.
gabr
+5  A: 

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.

Cesar Romero
+1  A: 

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

gabr
D2009 doesn't also.
Gamecat
A: 

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;

chester89
It is more Delphi like to use Assign. But a copy constructor could also do the trick.
Gamecat
+2  A: 

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())

Gerry
+1  A: 
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   

;)

+1  A: 

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.

Jeroen Pluimers
A: 

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

O Engenheiro