Autor |
Beitrag |
knittel
      
Beiträge: 71
Erhaltene Danke: 2
Win XP, Win7, openSUSE
Delphi 7
|
Verfasst: Di 19.02.13 00:37
Hallo allerseits,
führ ein 3D Programm, welches ich schreibe, hab ich mir eine Funktion geschrieben die einen Vektor normalisiert (nicht wundern ein Vektor ist hier vom Typ TMeleePosition (hat X,Y,Z als Werte))
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| function meNormalize(A: TMeleePosition): TMeleePosition; var length: glFloat; begin length := meLength(A); if (length = 0) then length := 1; result.X := A.X / length; result.Y := A.Y / length; result.Z := A.Z / length; end; |
Der Code ist auch nicht das Problem. Ich wollte mir nur zusätzlich noch eine Prozedur schreiben, die das selbe macht, deren Header aber so aussieht:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure meNormalize(var A: TMeleePosition); var length: glFloat; begin length := meLength(A); if (length = 0) then length := 1; A.X := A.X / length; A.Y := A.Y / length; A.Z := A.Z / length; end; |
Warum ich das möchte? Diese Funktion wird verdammt oft aufgerufen, und daher will ich immer die jeweils schnellere Version parat haben.
Mache ich soetwas: Vector := meNormalize(Vector); dann dauert das länger da er danach das result wieder in Vector schreiben muss.
Mache ich soetwas: Vector := meNormalize(meCrossProduct(VectorA, VectorB)); Dann wäre es ja blöd ich müsste dafür noch eine Variable einbauen, die dann erst normalisiert werden kann.
Daher wollte ich wissen ob ich mit einfach die beiden oben gezeigten Funktionen/Prozeduren mit overload ausstatten kann und dann nimmt er automatisch das richtige (das Problem ist ja, dass die beiden Funktionen die selben Parameter haben) oder muss ich eine der Funktionen umbennen?
Danke schon mal im vorraus.
_________________ "Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."
|
|
WasWeißDennIch
      
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: Di 19.02.13 09:23
Überladen wird nicht funktionieren, da für den Compiler nicht immer eindeutig erkennbar ist, welche der beiden Varianten gemeint ist. IMO wirst Du um ein Umbenennen nicht herumkommen.
|
|
Tranx
      
Beiträge: 648
Erhaltene Danke: 85
WIN 2000, WIN XP
D5 Prof
|
Verfasst: Di 19.02.13 10:19
Das entscheidende bei der Überladung von Prozeduren udn Funktionen ist die Unterschiedlichkeit der Parameterliste. Das heißt im Klartext, dass Prozeduren mit gleichen Parameterlisten (und in diesem Zusammenhang ist Var keine Unterscheidung, da der Typ gefragt ist, und nicht die Art der Übertragung/Speicherung/Übergabe) nicht gegenseitig überlagert werden dürfen. Wie oben schon erwähnt, prüft der Compiler anhand des Typs der Parameter, welche Funktion/Prozedur genommen wird. Hier geht das nicht, da beide Parameterlisten vom Typ her gleich sind.
_________________ Toleranz ist eine Grundvoraussetzung für das Leben.
|
|
Blup
      
Beiträge: 174
Erhaltene Danke: 43
|
Verfasst: Di 19.02.13 10:50
Wenn man die Prozedur als Methode des Records definiert, ist die gleiche Bezeichnung möglich.
Allerdings muss der Aufruf dann trotzdem anders notiert werden.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31:
| type TMeleePosition = record x,y,z: glFloat; procedure meNormalize; end;
function meNormalize(const A: TMeleePosition): TMeleePosition;
implementation
procedure TMeleePosition.meNormalize; var length: glFloat; begin length := meLength(A); if (length = 0) then Exit; X := X / length; Y := Y / length; Z := Z / length; end;
function meNormalize(const A: TMeleePosition): TMeleePosition; begin Result := A; Result.meNormalize; end;
Vector.meNormalize; Vector := meNormalize(meCrossProduct(VectorA, VectorB)); |
Für diesen Beitrag haben gedankt: knittel
|
|
Mr_Emre_D
      
Beiträge: 114
Erhaltene Danke: 14
|
Verfasst: Di 19.02.13 10:52
Wie wärs hiermit?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| function meNormalize(var A: TMeleePosition; const Apply: Boolean = false): TMeleePosition; var length: glFloat; begin length := meLength(A); if (length = 0) then length := 1; Result.X := A.X / length; Result.Y := A.Y / length; Result.Z := A.Z / length; if Apply then A := Result; end; |
Damit kannst du die Funktion weiterhin so aufrufen
meNormalize(irgendEinVektor)
Zustätzlich kannst du nun auch angeben, ob die Berechnung übernommen werden soll
meNormalize(irgendEinVektor, true)
|
|
WasWeißDennIch
      
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: Di 19.02.13 11:22
Für diesen Beitrag haben gedankt: knittel
|
|
knittel 
      
Beiträge: 71
Erhaltene Danke: 2
Win XP, Win7, openSUSE
Delphi 7
|
Verfasst: Di 19.02.13 13:46
Hallo nochmal,
erstmal vielen Dank für die vielen Antworten! Die Lösung von Blub gefällt mir zwar am besten, aber bei mir wirft er mir nen Compiler-Error entgegen beim starten (END expected but PROCEDURE found). Kann es sein, dass man Prozeduren für Records erst ab späteren Delphi Versionen nutzen kann (ich habe Delphi 7)? Ansonsten folge ich WasWeißDennIch's Rat und bennene die Prozedur um. Sollte aber kein Problem sein, wäre halt schön gewesen hätte es auch so funktioniert. 
_________________ "Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Di 19.02.13 15:16
knittel hat folgendes geschrieben : | Kann es sein, dass man Prozeduren für Records erst ab späteren Delphi Versionen nutzen kann (ich habe Delphi 7)? |
Die Syntax wurde geändert, in D7 ist das noch getrennt in object und record, also hier:
Delphi-Quelltext 1: 2: 3: 4: 5:
| type TMeleePosition = object x,y,z: glFloat; procedure meNormalize; end; |
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Für diesen Beitrag haben gedankt: knittel
|
|
Tranx
      
Beiträge: 648
Erhaltene Danke: 85
WIN 2000, WIN XP
D5 Prof
|
Verfasst: Di 19.02.13 16:50
Also, es ist zwar eine Krücke, aber das funktioniert (Delphi 5):
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51:
| unit xxx;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type pVektor = ^Vektor; Vektor = Record X, Y : EXTENDED; end;
var
procedure Test(var v : Vektor); overload; function Test(v : pVektor) : Vektor; overload; procedure TueWas;
implementation {$R *.DFM}
procedure Test(var v : Vektor); begin v.X := v.X + 1.0; v.Y := v.y + 1.0; end;
function Test(v : pVektor) : Vektor; overload; begin v^.X := v^.X + 1.0; v^.Y := v^.Y + 1.0; Result := v^; end;
procedure TueWas; var v : Vektor; pv : pVektor; begin v.X := 10.0; v.Y := - 4.0; Test(v); v := Test(@v); end;
end. |
Wenn Du als Funktionswert der Funktion "Kreuzprodukt zweier Vektoren" nicht den Vektor, sonder den Zeiger auf einen Vektor (pVektor) übergibst, so kann der Compiler erkennen, welche beiden Funktionen zu nehmen sind. Denn pVektor und Vektor sind unterschiedlich.
Vielleicht hilft Dir das.
_________________ Toleranz ist eine Grundvoraussetzung für das Leben.
Für diesen Beitrag haben gedankt: knittel
|
|
knittel 
      
Beiträge: 71
Erhaltene Danke: 2
Win XP, Win7, openSUSE
Delphi 7
|
Verfasst: Di 19.02.13 17:27
Vielen Dank an Matrok und Tranx. Mir gefallen beide Lösungen, würde aber gern Martoks Lösung testen.
Dazu eine Frage: Was genau ist denn hier der Unterschied zwischen record und object? Muss ich bei object erst Speicherplatz reservieren oder ähnliches, oder kann man es genauso anwenden wir einen record?
Danke nochmal und sorry, dass euch ihr so löchere 
_________________ "Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Di 19.02.13 17:50
knittel hat folgendes geschrieben : | Was genau ist denn hier der Unterschied zwischen record und object? Muss ich bei object erst Speicherplatz reservieren oder ähnliches, oder kann man es genauso anwenden wir einen record? |
Im Endeffekt gibt's keinen mehr. Object ist so ein Kompatibilitätszeug aus TurboPascal und stammt damit aus der Zeit vor class. Dabei werden die Daten bei Zuweisungen immer kopiert und Methoden haben keinen Self-Pointer (wie bei Klassen), sondern sind relativ verdingst. Das Ganze ist seit Jahren deprecated, aber anscheinend ist Embadingsda mal aufgefallen dass man sowas ja doch öfter braucht und wurde dann als "record-mit-Methoden" wieder eingeführt, weil man deprecated-Markierungen ja nicht so einfach wieder loswird.
Der generierte Code ist komplett identisch.
Seit Delphi 2009 stimmt das so auch nicht mehr ganz, weil records da noch mehr können, aber an der einfachen Verwendung ändert sich nix.
knittel hat folgendes geschrieben : | Danke nochmal und sorry, dass euch ihr so löchere  |
Kein Problem, dafür ist das Forum ja da 
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Für diesen Beitrag haben gedankt: knittel
|
|
|