Newsgroup: it.comp.lang.delphi
Titolo: Operator overloading?

Premetto di conoscere Delphi poco o nulla. Considerate l'esempio
sottostante:
type
  class pippo
    public i: integer;
  end;
var
  a1: pippo;
  a2: pippo;
begin
  a1.i := 1;
  a2.i := 2;
  a1 := a2;
  a2.i := 3;
end.
Mi aspettavo che Delphi copiasse i dati di a2 in a1, come avrebbe fatto C++,
invece dopo l'ultimo assegnamento trovo che anche a1.i = 3, segno che in
realtà a1 è diventato una sorta di alias di a2. E'possibile ottenere la
semplice copia dei dati di due oggetti della stessa classe? Esiste
l'operator overloading, con la possibilià di ridefinire il := ?
Grazie anticipatamente,
M.

non mi sembra che in delphi esista un operatore x fare cio.
Esiste un metodo: Assign (vedi classe TPersistent).
Bye
A

 ridefinire il := ?  Grazie anticipatamente,
La variabile d'instanza in realtà è un puntatore a 32 bit all'oggetto
precedentemente allocato dal suo costruttore. Per cui l'operazione di
assegnamento che hai effettuato non fa altro che:
A. Far puntare due variabili d'istanza allo stesso oggetto, per cui
ogni modifica la vedi riflessa nell'altra, proprio perché puntano allo
stesso oggetto.
B. Perdi il riferimento all'oggetto a1 creando un memory leak.
In Delphi puoi assegnare un oggetto all'altro con l'override del metodo
Assign, presente però solamente dalla TPersistent. In molte classi
della vcl, TFont, TStrings ecc.. il metodo è già implementato, mentre
in altre non è stato implementato.
ciao
guastatore

 l'operator overloading, con la possibilià di ridefinire il := ?
Che io sappia, in Delphi non esiste l'operator overloading, contrariamente a
quanto accade per l'overload dei metodi.
Tuttavia, quello che a te serve è il metodo Assign().
Tale metodo è definito nella classe TPersistent.
Ti riporto uno stralcio della documentazione:
-------
Copies the contents of another, similar object.
procedure Assign(Source: TPersistent);
Description
Call Assign to copy the properties or other attributes of one object from
another. The standard form of a call to Assign is
Destination.Assign(Source);
which tells the Destination object to copy the contents of the Source object
to itself.
------
Nella documentazione è scritto che le classi discendenti da TPersistent
devono
ridefinire l'implementazione di Assign(), dato che quella originale si
limita
a segnalare un EConvertError.
L'operatore ':=' da te utilizzato non effettua la copia, ma si limita a far
si
che a1 ed a2 puntino allo stesso oggetto.
Saluti,
Carmine

 end.
...
Oltre alle risposte che ti hanno dato, tieni conto che in Delphi il
constructor *deve* essere chiamato esplicitamente, cosi' come il
distruttore.
procedure aProc;
var p1, p1: TPippo;
begin
  p1 := TPippo.Create;
  p2 := TPippo.Create;
  try
    p1.i := 2;
    p2 := p1;
    writeln(p2.i); // scrive 2
  finally
    p1.Free;
    p2.Free;    // AV
  end;
  // una istanza di pippo e' ancora allocata
end;

Grazie a tutti per le vostre risposte!
Marco.

On Thu, 19 Jun 2003 10:22:30 +0200, "Muttley"
<m.trecat...@TOGLIQUAtiscalinet.it> wrote:
Io ti cosiglio oltre al metodo  Assign anche di fare un overload della
custruttore cosi da poter fare:
A := TPippo.Create;
A.i = 1;
B := TPippo.Create ( A );
e vorei ricordare che non è il metodo Assign che va overloadato ma è
il metodo protetto AssignTo
Source.AssignTo ( Des )
Il Razziatore,
The Only Good Windows is an uninstalled Windows
-----------------------------------------------
E-MAILs : IlRazziat...@NOSPAMnetscape.net
ICQ     : 67552596
-----------------------------------------------
Founder of MediaPlayer Project
http://mpp.iwebland.com

 Source.AssignTo ( Des )
Intanto il metodo va in *override* e non in *overload*. In genere però
si preferisce effettuare l'override del metodo Assign. Qualche post fa
avevo risposto sempre su questo argomento.
C'è una ragione per cui Assign della classe TPersistent chiama il
metodo AssignTo ed è la seguente:
nello sviluppo di un framework OO può accadere di  costruire delle
nuove classi compatibili, almeno in parte con quelle pre-esistenti.
Allora, se chiami il metodo Assign della classe pre-esistente e questa
non sa come gestire l'assegnazione, è probabile che chiamando il metodo
AssignTo della nuova classe si riesca a fare l'assegnamento, sempre che
le nuove classi del framework abbiano effettuato l'override del metodo
AssignTo.
Le magie del polimorfismo ;-))
ciao
guastatore
 

 Source.AssignTo ( Des )
Questa non la sapevo.
Grazie della dritta.
A

> Questa dell'overload del costruttore francamente non l'ho capita.
type
  tTuaClass = class
  public
    constructor Create; overload;
    constrcutr Create(AValore: integer); overload;
  end;
constructor create;
begin
  create(0);
end;
constructor create(AValore: integer);
begin
  inherited create;
  fValore := AValore;
end;
Quella di ridefinire i costruttori è una tecnica molto comoda ad esempio su
form quando ti serve fare qualcosa DURANTE LA CREAZIONE DEL FORM
Ad esempio:
constructorMy Create(AOwner: TComponent; var AQUalcheDato: integer);
begin
  inherited Create(AOwner);
 case AQUalcheDato of
   myset_valore1: Self.caption := 'INSERIMENTO'
...
end;
A


 end;
grazie Alberto, conosco l'overload dei metodi ;-) 
Solo che faticavo a capire l'attinenza con l'overload degli operatori.
Accertato che Delphi non ha l'overload degli operatori, il thread si
era incanalato praticamente sulla clonazione di oggetti e, di
conseguenza sul metodo Assign - AssignTo. Tutto qua. ;-))
Ciao
Antonio

Le magie del polimorfismo ;-))
Tutto vero.
Ma visto che TCustomForm ( mi pare ) ridefinisce AssignTo ( che viene
gia ridefinito da TWinControl ) e non ridefinisce Assign ( infatti
eredita direttamente da TPresent ). Ora quello ke hai detto è giusto
ma visto che i programmatori di delphi per le VCL non hanno ridefinto
Assign ma AssignTo secondo me sara meglio seguire il loro esempio, no?
Visto che stiamo facendo un po' divagazioni in Dephi la diretiva
"Virtual" ha lo stesso significato che il TurboPascal 7? O meglio
Io ho l' oggetto B che eredita dalla oggetto A. la classe b
ridefinisce un metodo di A ( tranto per dargli un nome diciamo D
questo metodo) 
ora il metodo C non ridefinito chima D. ora il TP7 se D non era
Virtual quando chiamavi C veniva chiamato il D di A. L'unico modo era
dichiarare D Virtual... in Delphi  e ancora cosi oppure Delphi è +
perspicace?


 che cio che passo al costruttore č un owner.
...
Anche quando istanzi una eccezione <g>?
Cmq, potrebbe essere consigliabile usare nomi significativi per i
costruttori (v. oltre)
Saluti
Paolo Arosio
type
TInfo = record
 ....
end;
TMultiConstructor = class(TObject)
public
  constructor Create;
  constructor Clone(From: TMultiConstructor); // copy constructor
  constructor CreateAndInit(anID: integer; aDesc: string);
  destructore Destroy; override;
  property Info: read fInfo write SetInfo;
  ...
protected
  procedure SetInfo(aInfo: TInfo);
  procedure SetMore(aMore: TObject);
  procedure CopyFrom(Source: TMultiConstructor); virtual;
private
  fID: integer;
  fDesc: string;
  fInfo: TInfo;
  fMore: TObject;
end;


    Via De Gasperi, 14 - 42019
    Scandiano (Reggio Emilia)

   constructor Clone(From: TMultiConstructor); // copy constructor
bella. Me ne "approprio"... :))
A

 Assign ma AssignTo secondo me sara meglio seguire il loro esempio, no?
Probabilmente i programmatori della VCL hanno operato proprio secondo
il principio che avevo definito precedentemente. Ridefinendo il metodo
AssignTo, salvano le classi di livello più basso.
Seguire l'esempio dei programmatori della VCL è senz'altro una buona
cosa.
Occorre, tuttavia, un minimo di discernimento. Seguire quanto hanno
fatto riguardo alla classe TList dalla versione 5 in poi, può portare a
codice inefficiente oltre che andare contro tutti i principi della OOP.
In questa classe hanno inserito un metodo virtuale Notify che viene
chiamato ogni volta che un oggetto contenuto viene cancellato allo
scopo di supportare questa operazione per la nuova classe TObjectList.
Notify nella classe TList non fa nulla, ma per ogni cancellazione viene
chiamato. Forse ancora peggiore è il fatto che abbiano modificato una
classe di livello superiore al solo scopo di supportare un nuovo metodo
in una nuova classe che eredita da essa. Sarebbe stato più opportuno
usare la delegazione piuttosto che l'eredità ? Io dico di sì.
Ciao
Antonio


Si scusa mi sono spagliato.
Precisamente nel oridine TForm eredita il metodo AssignTo da
TWinControl che lo ridefinisce chimando AssignTo di TControl che
chiama a sua volta quello di TPersistent
