Autor Beitrag
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Di 22.02.11 01:05 
Ich möchte ein Objekt als Referenzparamter übergeben.
Meine Funktion sieht so aus:
ausblenden Delphi-Quelltext
1:
procedure RegisterMerge(var aWhat:TMergeable); overload;					

TMergeable ist genau die Klasse, in der diese Funktion definiert wird und wird von TObject abgeleitet.

Jetzt habe ich eine Klasse, die 2 mal von dieser abgeleitet wurde.
Bsp:
ausblenden Delphi-Quelltext
1:
2:
TFoo=class(TMergeable);
TBar=class(TFoo);

Wenn ich jetzt RegisterMerge mit einer Instanz von TBar aufrufen will, sagt der Compiler mir, dass ich die nicht mit diesen Argumenten aufrufen kann.
Definiere ich die Funktion so:
ausblenden Delphi-Quelltext
1:
procedure RegisterMerge(var aWhat:PMergeable); overload//mit PMergeable=^TMergeable					

und rufe die mit RegisterMerhe(@Bar) auf ist alles ok. Aber ist unschön mit dem @

Was läuft da schief? Errorinsight meckert (ausnahmsweise) mal nicht...
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 22.02.11 01:23 
user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
Wenn ich jetzt RegisterMerge mit einer Instanz von TBar aufrufen will, sagt der Compiler mir, dass ich die nicht mit diesen Argumenten aufrufen kann.
Und das aus gutem Grund. Denn sonst könnte die Methode in eine TBar-Variable ein TMergeable-Objekt stecken, was man wohl lieber vermeiden sollte ;) .

_________________
>λ=
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 22.02.11 02:04 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Und das aus gutem Grund. Denn sonst könnte die Methode in eine TBar-Variable ein TMergeable-Objekt stecken, was man wohl lieber vermeiden sollte ;) .
Stimmt, aber er probiert ja genau das Gegenteil: TBar-Objekt in TMergeable-Variable.

Es müsste funktionieren, wäre der Parameter nicht ein Var-Parameter. Ich vermute mal, hier schlägt sich das Klassenmodell mit der Regel dass Variablenparameter immer genau vom Typ des Parameters sein müssen.

Wird sich wohl nicht ändern lassen.... :nixweiss:

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

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: Di 22.02.11 05:11 
Genau, bei nicht VAR-Parametern funktioniert das. Aber warum unbedingt ein VAR-Parameter? Welchen Nutzen hätte das? Ich will doch nicht den Typ ändern, ich will in der Regel doch bloß die Typ-Methoden und Eigenschaften nutzen, oder sehe iuchg das falsch?
Zumal, ich hoffe ich liege da nicht verkehrt, ist die Übergabe einem Typ als Parameter so etwas wie die Übergabe eines Zeigers auf den Typ. Ich greife also auf den Typ selber zu. Und somit kann ich auch alle öffentlich deklarierten Methoden/Eigenschaften nutzen und Variablen ändern, und zwar dauerhaft.

_________________
Toleranz ist eine Grundvoraussetzung für das Leben.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 22.02.11 07:51 
Richtig, hier ist ein Assign vermutlich sinnvoller, wenn nur Daten befüllt werden sollen. Denn wenn RegisterMerge eine Factory-Funktionalität haben soll, dann sollte der Wert als Rückgabewert definiert werden und die Funktion entsprechend heißen.

Denn was passiert sonst mit dem alten Objekt (denn es ist ja ein var- und kein out-Parameter)? Wird es darin auch freigegeben? Ist es anderweitig noch gespeichert? Alles nicht so ganz sauber.

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
Definiere ich die Funktion so:
ausblenden Delphi-Quelltext
1:
procedure RegisterMerge(var aWhat:PMergeable); overload//mit PMergeable=^TMergeable					

und rufe die mit RegisterMerhe(@Bar) auf ist alles ok. Aber ist unschön mit dem @
Das finde ich noch nicht einmal. Denn dadurch sieht man zumindest, dass das Objekt neu zugewiesen werden könnte. Am Namen der Prozedur lässt sich das ja nicht wirklich erkennen...

Schreib doch einfach einmal den Hintergrund zu dem Quelltext, also du damit eigentlich machen möchtest. ;-) Dann hat jemand vielleicht eine bessere Umsetzungsmöglichkeit.
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 22.02.11 11:20 
user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Stimmt, aber er probiert ja genau das Gegenteil: TBar-Objekt in TMergeable-Variable.
Er übergibt eine TBar-Variable an die Methode, also zeigt der TMergeable-Parameter auf diese Variable. Und wenn er diesem Parameter nun innerhalb der Klasse ein TMergeable-Objekt zuweisen würde ;) ...
Man kann es auch so sehen: Der Typ der übergebenen Variable muss kovariant zu einem In-Parameter sein und kontravariant zu einem Out-Parameter (einem out TBar kann ich auch eine TMergeable-Variable übergeben), also sind var-Parameter logischerweise invariant.



user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
Definiere ich die Funktion so:
ausblenden Delphi-Quelltext
1:
procedure RegisterMerge(var aWhat:PMergeable); overload//mit PMergeable=^TMergeable					

und rufe die mit RegisterMerhe(@Bar) auf ist alles ok. Aber ist unschön mit dem @
Das finde ich noch nicht einmal. Denn dadurch sieht man zumindest, dass das Objekt neu zugewiesen werden könnte. Am Namen der Prozedur lässt sich das ja nicht wirklich erkennen...
Und das var hat das nicht signalisiert :gruebel: ?

_________________
>λ=
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 22.02.11 11:46 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Und das var hat das nicht signalisiert :gruebel: ?
Nicht beim Aufruf. ;-)
Flamefire Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Di 22.02.11 12:55 
Es geht darum, Objekte zu "mergen" also zusammenzuführen. Damit das ganze auch über mehrere Vererbungsstufen einfach funktioniert, registriere ich einfach alles, was gemergt werden soll. Das ganze getrennt nach Strings, einfachen Datentypen und TMergeable Objekten. Damit ich (besonders bei Strings und Objekten) auch am Ende die tatsächliche Instanz habe brauche ich natürlich einen Zeiger auf den String/Objekt.
Sieht am Ende ungefähr so aus:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TLSMergeable.RegisterMerge(aWhat: PLSMergeable);
begin
  if(not Assigned(FMergeObjs)) then FMergeObjs:=TList<PLSMergeable>.Create;
  FMergeObjs.Add(aWhat);
end;

und dann:
ausblenden Delphi-Quelltext
1:
2:
3:
  if(Assigned(FMergeObjs)) then
    for i := 0 to FMergeObjs.Count - 1 do
      FMergeObjs[i]^.Merge(TLSMergeable(AOther).FMergeObjs[i]^);


Macht das ganze doch etwas übersichtlicher, als in jedem Objekt die Merge Methode zu implementieren und dann alles einzeln zu kopieren. Ist mir zuviel tipparbeit ;)