2015-10-06 24 views
6

Delphi documentation mówi, że możliwe jest przeciążenie operatorów Inc i Dec; Nie widzę żadnego ważnego sposobu, aby to zrobić. Oto próby przeciążenia operatora Inc; niektóre próby prowadzą do kompilacji błędów, niektóre do naruszenia praw dostępu do środowiska wykonawczego (Delphi XE):Jak przeciążyć operatorów Inc (Dec) w 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. 

Odpowiedz

7

Podpis operatora jest nieprawidłowy. Powinno być:

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

lub

class operator Inc(A: TMyInt): TMyInt; 

Nie można używać parametru var.

Ten program

{$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. 

produkuje ten wyjściowe:

 
1 

dyskusję

Jest to dość nietypowe, gdy operator przeciążony. Pod względem użytkowania operator jest mutacją na miejscu. Jednak po przeciążeniu działa jak operator dodający z niejawnym dodatkiem.

Więc w kodzie powyżej tej linii:

Inc(A); 

skutecznie przekształcony

A := TMyInt.Inc(A); 

a następnie zestawiane.

Jeśli chcesz zachować prawdziwą semantykę mutacji w miejscu i uniknąć kopiowania skojarzonego z tym operatorem, to uważam, że musisz użyć metody tego typu.

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

Mutacja parametru const wygląda dziwnie, prawda? Również prototyp funkcji z zwracaną wartością do zignorowania? – kludg

+1

Wygląda jak mutacja na stronie wywołania, ale kompilator tłumaczy 'Inc (MyInt)' na 'MyInt: = TMyInt.Inc (MyInt);' Tak, to bardzo dziwne. Nie przeciążałbym 'Inc' i' Dec'. –

Powiązane problemy