2015-10-06 48 views
6

Delphi documentation afferma che è possibile sovraccaricare gli operatori Inc e Dec; Non vedo un modo valido per farlo. Ecco i tentativi di sovraccaricare l'operatore Inc; alcuni tentativi portano alla compilazione di errori, alcuni alla violazione dell'accesso al runtime (Delphi XE):Come sovraccaricare gli operatori Inc (Dec) in Delphi?

program OverloadInc; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils; 

type 
    TMyInt = record 
    FValue: Integer; 
// class operator Inc(var A: TMyInt); DCC error E2023 
    class operator Inc(var A: TMyInt): TMyInt; 
    property Value: Integer read FValue write FValue; 
    end; 

class operator TMyInt.Inc(var A: TMyInt): TMyInt; 
begin 
    Inc(A.FValue); 
    Result:= A; 
end; 

type 
    TMyInt2 = record 
    FValue: Integer; 
    class operator Inc(A: TMyInt2): TMyInt2; 
    property Value: Integer read FValue write FValue; 
    end; 

class operator TMyInt2.Inc(A: TMyInt2): TMyInt2; 
begin 
    Result.FValue:= A.FValue + 1; 
end; 

procedure Test; 
var 
    A: TMyInt; 

begin 
    A.FValue:= 0; 
    Inc(A); 
    Writeln(A.FValue); 
end; 

procedure Test2; 
var 
    A: TMyInt2; 
    I: Integer; 

begin 
    A.FValue:= 0; 
// A:= Inc(A); DCC error E2010 
    Writeln(A.FValue); 
end; 

begin 
    try 
    Test;  // access violation 
// Test2; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    Readln; 
end. 

risposta

7

La firma dell'operatore è errata. Dovrebbe essere:

class operator Inc(const A: TMyInt): TMyInt; 

o

class operator Inc(A: TMyInt): TMyInt; 

Non è possibile utilizzare un parametro var.

Questo programma

{$APPTYPE CONSOLE} 

type 
    TMyInt = record 
    FValue: Integer; 
    class operator Inc(const A: TMyInt): TMyInt; 
    property Value: Integer read FValue write FValue; 
    end; 

class operator TMyInt.Inc(const A: TMyInt): TMyInt; 
begin 
    Result.FValue := A.FValue + 1; 
end; 

procedure Test; 
var 
    A: TMyInt; 
begin 
    A.FValue := 0; 
    Inc(A); 
    Writeln(A.FValue); 
end; 

begin 
    Test; 
    Readln; 
end. 

produce questo output:

 
1 

Discussione

È un operatore piuttosto insolito caso di sovraccarico. In termini di utilizzo l'operatore è una mutazione sul posto. Tuttavia, quando sovraccaricato, funziona come un operatore di addizione con un adduto implicito di uno.

Così, nel codice sopra di questa linea:

Inc(A); 

effettivamente trasformata in

A := TMyInt.Inc(A); 

e poi compilato.

Se si desidera mantenere una vera semantica della mutazione sul posto ed evitare la copia associata a questo operatore, credo che sia necessario utilizzare un metodo del tipo.

procedure Inc; inline; 
.... 
procedure TMyInt.Inc; 
begin 
    inc(FValue); 
end; 
+1

La mutazione del parametro const è strana, non è vero? Anche il prototipo di funzione con valore di ritorno da ignorare? – kludg

+1

Sembra una mutazione sul sito di chiamata, ma il compilatore traduce 'Inc (MyInt)' in 'MyInt: = TMyInt.Inc (MyInt);' Sì è molto strano. Non sovraccarico 'Inc' e' Dec'. –