![]() |
Übergabeparameter verfälscht bei Aufruf einer Funktion
Hi, ich habe folgendes Problem: Wenn ich eine Funktion per Funktionszeiger aufrufe, sind die Übergabeparameter irgendwie verfälscht. Ich kann mir das nicht erklären.
Delphi-Quellcode:
In dem Moment, wenn ich in TIntegerComparer.Compare die Funktion _ComparerFunc(x, y) aufrufen, sind in der verlinkten Funktion DefaultComparerFunc die Parameter x und y auf einmal irgendwie anders anders!? Ich habe mal testweise feste Zahlen bei ComparerFunc angegeben, doch irgendwie hat dann y den Wert von x der Vorgänger funktion. Und das übergebene y wird zu x.
{------------------------------------------------------------------------------}
{ TIntegerComparer {------------------------------------------------------------------------------} TIntegerComparerFunc = function(x: Integer; y: Integer): Integer; TIntegerComparer = class private _ComparerFunc: TIntegerComparerFunc; function GetComparerFunc: TIntegerComparerFunc; procedure SetComparerFunc(func: TIntegerComparerFunc); public function Compare(x: Integer; y: Integer): Integer; property ComparerFunc: TIntegerComparerFunc read GetComparerFunc write SetComparerFunc; function DefaultComparerFunc(x: Integer; y: Integer): Integer; Constructor Create; Destructor Destroy; override; end; ... {------------------------------------------------------------------------------} { TIntegerComparer {------------------------------------------------------------------------------} Constructor TIntegerComparer.Create; Begin _ComparerFunc := @TIntegerComparer.DefaultComparerFunc; End; {------------------------------------------------------------------------------} Destructor TIntegerComparer.Destroy; Begin Inherited; End; {------------------------------------------------------------------------------} function TIntegerComparer.GetComparerFunc: TIntegerComparerFunc; Begin result := _ComparerFunc; End; {------------------------------------------------------------------------------} procedure TIntegerComparer.SetComparerFunc(func: TIntegerComparerFunc); Begin _ComparerFunc := func; End; {------------------------------------------------------------------------------} function TIntegerComparer.Compare(x: Integer; y: Integer): Integer; begin if x = y then result := 0 else if (x < y) then result := -1 else result := 1; //exit; if @_ComparerFunc = nil then RaiseException('TIntegerComparer.Compare: Keine Vergleichsfunktion festgelegt'); result := _ComparerFunc(x, y); end; {------------------------------------------------------------------------------} function TIntegerComparer.DefaultComparerFunc(x: Integer; y: Integer): Integer; begin if x = y then result := 0 else if (x < y) then result := -1 else result := 1; end; Ich peil gar nix mehr :gruebel: |
Re: Übergabeparameter verfälscht bei Aufruf einer Funktion
Moin!
Ist auch logisch. Du hast als Vergleichsroutine eine normale Routine definiert und weisst ihr durch böse Tricks eine Methode zu. Damit bekommt dein X Wert beim Aufruf die Instanz und der Y Wert den X Wert. Abgesehen davon, das der Stack durcheinander kommt, weil ja der gepushte Y Wert liegen bleibt.... MfG Muetze1 |
Re: Übergabeparameter verfälscht bei Aufruf einer Funktion
Moin Arakis,
Methoden haben noch einen impliziten Parameter, der vor den anderen kommt, nämlich self. Intern sieht, z.B.,
Delphi-Quellcode:
so aus:
function TIntegerComparer.DefaultComparerFunc(x: Integer; y: Integer): Integer;
Code:
function TIntegerComparer.DefaultComparerFunc([color=red]self: TIntegerComparer;[/color]x: Integer; y: Integer): Integer;
|
Re: Übergabeparameter verfälscht bei Aufruf einer Funktion
Was muss ich denn da ändern? Ich weiß leider nur unvollständig, wie man mit Funktionszeigern umgeht.
|
Re: Übergabeparameter verfälscht bei Aufruf einer Funktion
Moin!
1. Du hast als Vergleichsprocedure eine Methode:
Delphi-Quellcode:
Oder
{------------------------------------------------------------------------------}
{ TIntegerComparer {------------------------------------------------------------------------------} TIntegerComparerFunc = function(x: Integer; y: Integer): Integer Of Object; TIntegerComparer = class private _ComparerFunc: TIntegerComparerFunc; function GetComparerFunc: TIntegerComparerFunc; procedure SetComparerFunc(func: TIntegerComparerFunc); public function Compare(x: Integer; y: Integer): Integer; property ComparerFunc: TIntegerComparerFunc read GetComparerFunc write SetComparerFunc; function DefaultComparerFunc(x: Integer; y: Integer): Integer; Constructor Create; Destructor Destroy; override; end; ... {------------------------------------------------------------------------------} { TIntegerComparer {------------------------------------------------------------------------------} Constructor TIntegerComparer.Create; Begin _ComparerFunc := DefaultComparerFunc; End; {------------------------------------------------------------------------------} Destructor TIntegerComparer.Destroy; Begin Inherited; End; {------------------------------------------------------------------------------} function TIntegerComparer.GetComparerFunc: TIntegerComparerFunc; Begin result := _ComparerFunc; End; {------------------------------------------------------------------------------} procedure TIntegerComparer.SetComparerFunc(func: TIntegerComparerFunc); Begin _ComparerFunc := func; End; {------------------------------------------------------------------------------} function TIntegerComparer.Compare(x: Integer; y: Integer): Integer; begin if x = y then result := 0 else if (x < y) then result := -1 else result := 1; //exit; if Not Assigned(_ComparerFunc) then RaiseException('TIntegerComparer.Compare: Keine Vergleichsfunktion festgelegt'); result := _ComparerFunc(x, y); end; {------------------------------------------------------------------------------} function TIntegerComparer.DefaultComparerFunc(x: Integer; y: Integer): Integer; begin if x = y then result := 0 else if (x < y) then result := -1 else result := 1; end; 2. eine normale Procedure/Funktion
Delphi-Quellcode:
MfG
{------------------------------------------------------------------------------}
{ TIntegerComparer {------------------------------------------------------------------------------} TIntegerComparerFunc = function(x: Integer; y: Integer): Integer; TIntegerComparer = class private _ComparerFunc: TIntegerComparerFunc; function GetComparerFunc: TIntegerComparerFunc; procedure SetComparerFunc(func: TIntegerComparerFunc); public function Compare(x: Integer; y: Integer): Integer; property ComparerFunc: TIntegerComparerFunc read GetComparerFunc write SetComparerFunc; Constructor Create; Destructor Destroy; override; end; ... {------------------------------------------------------------------------------} function DefaultComparerFunc(x: Integer; y: Integer): Integer; begin if x = y then result := 0 else if (x < y) then result := -1 else result := 1; end; {------------------------------------------------------------------------------} { TIntegerComparer {------------------------------------------------------------------------------} Constructor TIntegerComparer.Create; Begin _ComparerFunc := DefaultComparerFunc; End; {------------------------------------------------------------------------------} Destructor TIntegerComparer.Destroy; Begin Inherited; End; {------------------------------------------------------------------------------} function TIntegerComparer.GetComparerFunc: TIntegerComparerFunc; Begin result := _ComparerFunc; End; {------------------------------------------------------------------------------} procedure TIntegerComparer.SetComparerFunc(func: TIntegerComparerFunc); Begin _ComparerFunc := func; End; {------------------------------------------------------------------------------} function TIntegerComparer.Compare(x: Integer; y: Integer): Integer; begin if x = y then result := 0 else if (x < y) then result := -1 else result := 1; //exit; if Not Assigned(_ComparerFunc) then RaiseException('TIntegerComparer.Compare: Keine Vergleichsfunktion festgelegt'); result := _ComparerFunc(x, y); end; Muetze1 |
Re: Übergabeparameter verfälscht bei Aufruf einer Funktion
Hm. Also Quelltext2 scheint genau der selbe zu sein wie meine Version. Wo ist denn dort was anders? Und bei Quelltext eins bekomme ich in der Funktion TIntegerComparer.Create die Fehlermeldung "[Error] Larne.pas(1119): Incompatible types: 'regular procedure and method pointer'" wenn ich "_ComparerFunc := DefaultComparerFunc;" statt " _ComparerFunc := @TIntegerComparer.DefaultComparerFunc;" schreibe.
|
Re: Übergabeparameter verfälscht bei Aufruf einer Funktion
Moin!
Zitat:
Zitat:
MfG Muetze1 |
Re: Übergabeparameter verfälscht bei Aufruf einer Funktion
Ach, jetzt habe ich verstanden und es funktioniert auch. Was hat denn dieses "of Object" auf sich?
Also mein spärliches Wissen über Funktionszeiger habe ich hier von: ![]() |
Re: Übergabeparameter verfälscht bei Aufruf einer Funktion
Delphi-Quellcode:
type
TIntegerComparerFunc = function(X, Y: Integer): Integer of object; TIntegerComparer = class(TObject) private FComparerFunc: TIntegerComparerFunc; public function Compare(X, Y: Integer): Integer; property CustomCompare: TIntegerComparerFunc read FComparerFunc write FComparerFunc; end;
Delphi-Quellcode:
oder so: Wenn du lieber Prozeduren anstatt von Methoden bevorzugst.
function TIntegerComparer.Compare(X, Y: Integer): Integer;
begin if Assigned(FComparerFunc) then Result := FComparerFunc(X, Y) else begin if X = Y then Result := 0 else if X < Y then Result := -1 else Result := 1; end; end;
Delphi-Quellcode:
type
TIntegerComparerFunc = function(X, Y: Integer): Integer; TIntegerComparer = class(TObject) private FComparerFunc: TIntegerComparerFunc; public function Compare(X, Y: Integer): Integer; property CustomCompare: TIntegerComparerFunc read FComparerFunc write FComparerFunc; end;
Delphi-Quellcode:
function TIntegerComparer.Compare(X, Y: Integer): Integer;
begin if Assigned(FComparerFunc) then Result := FComparerFunc(X, Y) else begin if X = Y then Result := 0 else if X < Y then Result := -1 else Result := 1; end; end; |
Re: Übergabeparameter verfälscht bei Aufruf einer Funktion
Moin!
"Of Object" besagt aus, das du dort keine normale Funktionen zuweisen kannst, sondern es muss eine Funktion einer Klasse sein (also eine Methode). Alles andere lässt der Compiler nicht zu - ausser du machst es auf diesen bösen Weg mit der Adresse der Funktion, wie du es bei deinem originalen Code gemacht hast. Damit umgehst du die Typprüfung des Compilers und beseitigst somit seine Einwände - die aber berechtigt sind. Wie du siehst funktionieren beide Varianten nun mit einer direkten Zuweisung ohne Verrenkungen... Und Sprints Methode über eine Property die Sortiermethode zu zuweisen ist genauso gut geeignet wie die Methode von TList, die einfach die Methode im Sort Aufruf mitnimmt... MfG Muetze1 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:00 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz