Autor Beitrag
knittel
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: 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))

ausblenden 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 = 0then 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:

ausblenden 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 = 0then 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 174
Erhaltene Danke: 43



BeitragVerfasst: 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.
ausblenden volle Höhe Delphi-Quelltext
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 = 0then
    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; // Methode
Vector := meNormalize(meCrossProduct(VectorA, VectorB)); // Funktion

Für diesen Beitrag haben gedankt: knittel
Mr_Emre_D
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 114
Erhaltene Danke: 14



BeitragVerfasst: Di 19.02.13 10:52 
Wie wärs hiermit?
ausblenden 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 = 0then 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Di 19.02.13 11:22 
user profile iconknittel hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconMr_Emre_D hat folgendes geschrieben Zum zitierten Posting springen:

ausblenden 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 = 0then length := 1;
  Result.X := A.X / length;
  Result.Y := A.Y / length;
  Result.Z := A.Z / length;
  if Apply then A := Result;
end;

Unter diesem Gesichtspunkt sind nun beide Nachteile vereint :mrgreen:

Für diesen Beitrag haben gedankt: knittel
knittel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Di 19.02.13 15:16 
user profile iconknittel hat folgendes geschrieben Zum zitierten Posting springen:
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:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: Di 19.02.13 16:50 
Also, es ist zwar eine Krücke, aber das funktioniert (Delphi 5):

ausblenden volle Höhe Delphi-Quelltext
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Di 19.02.13 17:50 
user profile iconknittel hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconknittel hat folgendes geschrieben Zum zitierten Posting springen:
Danke nochmal und sorry, dass euch ihr so löchere ;)
Kein Problem, dafür ist das Forum ja da :zwinker:

_________________
"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