7
Tags:
delphi
Skrevet af
Bruger #782
@ 21.06.2007
Formål
Formålet med denne artikel er at udbredde forståelsen af Delphi's implementation af Operator Overloading[OO].
Jeg vil primært forholde mig til Win32 OO, som blev indført i år 2005. Det vil for de fleste nok kun være interresant hvis du har fået Turbo Delphi Explorer.
Det kræves i denne artikel at du ved hvordan man definerer en record.
Operator Overloading
OO kan for Win32 compileren kun foregå med records.
OO kan benyttes i mange situationer, men de steder hvor det er mest nærtliggende, er steder hvor man har interesse i, at programmere en løsning af et matematisk problem, der involverer vektorer eller andre matricer f.eks.
Jeg vil nu definere en vektor klasse:
type
TVector = record
x,y: single;
end;
Hvis man tidligere ville udføre aritmetiske operationer med en bunke af sådan nogle vektorer, så skulle man have en masse funktionskald.
Jeg kan hurtigt definere et par stykker, men jeg vil ikke kommentere yderligere på denne kode da den kun er her for at vise princippet:
function vecAdd(a,b: TVector): TVector;
begin
Result.x := a.x+b.x;
Result.y := a.y+b.y;
end;
function vecSub(a,b: TVector): TVector;
begin
Result.x := a.x-b.x;
Result.y := a.y-b.y;
end;
function vecMult(a,b: TVector): TVector;
begin
Result.x := a.x*b.x;
Result.y := a.y*b.y;
end;
Kikker vi på en operation, der matematisk ville defineres som (a+b)*(a-b) hvor a og b er to vektorer så vil man med den traditionelle fremgangsmåde i Delphi skulle skrive:
var x, a,b: TVector;
begin
//allokering af a og b her
a.x := 2;
a.y := 5;
b.x := 6;
b.y := 7;
//udregning af (a+b)*(a-b)
x := vecMult(vecAdd(a,b), vecSub(a,b));
end;
Dette kan man sikkert nok leve med men det ser ikke synderlig godt ud. Og ved større operationer kan det godt blive svært at finde rundt i.
Vi definerer derfor nogle nye operatorere!
Vi skal have fat i vores grunddefinition af TVector igen nu. Der er i Delphi et nyt keyword der hedder
operator. Dette bruges til definitionen af en operator. Nedenfor er vist en simpel udvidelse af vores vektor:
type
TVector = record
x,y: single;
class operator Add(v1,v2: TVector): TVector;
end;
...
implementation
...
class operator TVector.Add(v1,v2: TVector): TVector;
begin
//denne funktion bliver kaldt når der i programmet bliver skrevet v1+v2, hvor v1 og v2 er af typen TVector
end;
Der findes en lang række operatorere du kan definere men du kan ikke definere nye som man kan i C++. Du kan for eksempel ikke redefinere hvordan ^ virker. Du kan se listen i sidste afsnit
For at udvide TVector klassen så alle de nødvendige operatorere bliver defineret så definerer vi lige operatorere for +,-,*
type
TVector = record
x,y: single;
class operator Add(v1,v2: TVector): TVector;
class operator Subtract(v1,v2: TVector): TVector;
class operator Multiply(v1,v2: TVector): TVector;
end;
...
implementation
...
class operator TVector.Add(v1,v2: TVector): TVector;
begin
Result.x := a.x+b.x;
Result.y := a.y+b.y;
end;
class operator TVector.Subtract(v1,v2: TVector): TVector;
begin
Result.x := a.x-b.x;
Result.y := a.y-b.y;
end;
class operator TVector.Multiply(v1,v2: TVector): TVector;
begin
Result.x := a.x*b.x;
Result.y := a.y*b.y;
end;
Med dette gjort kan vi nu compile og køre følgende kode f.eks:
var x, a,b: TVector;
begin
//allokering af a og b her
a.x := 2;
a.y := 5;
b.x := 6;
b.y := 7;
//udregning af (a+b)*(a-b)
x := (a+b)*(a-b);
end;
Afslutning
Jeg håber dette har givet en forståelse for operator overloading i Delphi. Det er klart at man kan bruge disse til at lette ens arbejde en del på visse punkter, men når man kommer ud i at skulle kombinere operatorere på flere forskellige typer så kan man blive nød til at lave noget mindre flot kode for at kunne løse det.
Liste
Implicitclass operator Implicit(a : type) : resultType;
Denne operator skal bruges når man konverterer en type til en anden uden at bruge eksplicit typecast. Eksempel:
var a: TVector;
x: Single;
begin
a := x; //har vil TVector.Implicit(x) blive kaldt
end;
Explicitclass operator Explicit(a: type) : resultType;
Denne virker nogenlunde som Implicit bortset fra at du her skal lave en traditionel typecast. Eksempel:
var a: TVector;
x: Single;
begin
a := TVector(x); //har vil TVector.Explicit(x) blive kaldt
end;
Negativeclass operator Negative(a: type) : resultType;
-
Positiveclass operator Positive(a: type): resultType;
+
Incclass operator Inc(a: type) : resultType;
Inc
Decclass operator Dec(a: type): resultType
Dec
LogicalNotclass operator LogicalNot(a: type): resultType;
not
BitwiseNotclass operator BitwiseNot(a: type): resultType;
not
Truncclass operator Trunc(a: type): resultType;
Trunc
Roundclass operator Round(a: type): resultType;
Round
Equalclass operator Equal(a: type; b: type) : Boolean;
=
NotEqualclass operator NotEqual(a: type; b: type): Boolean;
<>
GreaterThanclass operator GreaterThan(a: type; b: type) Boolean;
>
GreaterThanOrEqualclass operator GreaterThanOrEqual(a: type; b: type): resultType;
>=
LessThanclass operator LessThan(a: type; b: type): resultType;
<
LessThanOrEqualclass operator LessThanOrEqual(a: type; b: type): resultType;
<=
Addclass operator Add(a: type; b: type): resultType;
+
Subtractclass operator Subtract(a: type; b: type) : resultType;
-
Multiplyclass operator Multiply(a: type; b: type) : resultType;
*
Divideclass operator Divide(a: type; b: type) : resultType;
/
IntDivideclass operator IntDivide(a: type; b: type): resultType;
div
Modulusclass operator Modulus(a: type; b: type): resultType;
mod
ShiftLeftclass operator ShiftLeft(a: type; b: type): resultType;
shl
ShiftRightclass operator ShiftRight(a: type; b: type): resultType;
shr
LogicalAndclass operator LogicalAnd(a: type; b: type): resultType;
and
LogicalOrclass operator LogicalOr(a: type; b: type): resultType;
or
LogicalXorclass operator LogicalXor(a: type; b: type): resultType;
xor
BitwiseAndclass operator BitwiseAnd(a: type; b: type): resultType;
and
BitwiseOrclass operator BitwiseOr(a: type; b: type): resultType;
or
BitwiseXorclass operator BitwiseXor(a: type; b: type): resultType;
xor
Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.
Del også gerne artiklen med dine Facebook venner:
Kommentarer (7)
Syntes det er en utrolig dårlig forklaring af hvad artiklen handler om. Man får ikke at vide hvad det er, og hvad det kan bruges tid - og sår står man hurtigt af når man vil læse artiklen.
Det er jeg naturligvis ked af at du synes. Jeg skrev artiklen da jeg syntes det var utrolig svært at finde ud af hvordan delphi's operator overloading virkede. Operator overloading er ikke nogen ny teknik(i andet end Delphi) og det virkede naturligt for mig ikke at forklare det på tidspunktet.
Hm hvad er gør teknikken så?
Redefinerer(overloader) den måde som de aritmetiske og boolske operatorere fungerer for visse kombinationer af typer.
Kanon, vidste ikke det var kommet med Turbo, så er der da endeligt noget godt ved den opgradering.
Navnet siger vel også lidt sig selv. En programmør bør vide, hvad en operator er, og det er da stortset almen viden, hvad det vil sige at 'overloade'.
hvor fedt!
Jeg anede ikke at Delphi understøttede operator overload. Har ofte savnet det, især ifm. vektorer naturligvis.
Det er jo så lidt ærgeligt at det kun fungerer på records, men det er da en start.
Du skal være
logget ind for at skrive en kommentar.