Hey ho zusammen,
nachdem im Vorherigen Thread ein paar basics besprochen wurden, würde ich gerne die Community strapazieren und ein paar weitere Fragen stellen und zwar bezüglich Referenzen, Pointer, Funktionpointer und enumerations. Das rührt daher, dass mir noch nicht 100%ig klar ist, wann ein typ via reference und wann via value übergeben wird.
Sagen wir mal wir haben folgende klasse:
Code:
C = class(TObject)
public
lab : TLabel;
procedure SetLabel(var l : TLable);
begin
lab := l;
end;
end;
(ich bin mir ziemlich sicher, dass das da oben nicht zu komplilieren ist, aber vom prinzip her sollte es klar sein ^^) Meine Frage: Erhält hier C.lab wirklich die reference des objektes l? Und was passiert wenn ich das keyword 'var' weglasse. Passiert dann genau dasselbe wie mit?
Kommen wir zu den Pointern: Werden pointer überhaupt noch benutzt? Es gibt das keyword 'unsafe'. Macht es Sinn mit pointern zu arbeiten?
Funktionspointer: Wie ist es möglich der Klasse C einen Funktionspointer zu übergeben und dann mit einer procedure auszuführen? Ich habe leider auch hier nichts stichhaltiges im Internet gefunden.
Enumerations: Im vorherigen Thread hab ich die Frage schon gestellt aber ich stell sie hier nochmal, da sie noch nicht beantwortet ist: Wieso muss ich ein enum immer in einen Integer casten? D.h. folgendes würde nicht gehen:
Code:
E = (e1 = 0, e2);
procedure F
var
i : array[0..2] of integer;
begin
i[e1] := 5;
e[e2] := 9;
end;
Man muss es stets in ein integer casten:
Code:
procedure F
var
i : array[0..2] of integer;
begin
i[Integer(e1)] := 5;
e[Integer(e2)] := 9;
end;
Ok das wars erstmal. Ich hoffe der ein oder andere kann mir weiterhelfen. Ob durch eigene erklärung oder link.
Vielen Dank schonmal im Vorraus
Cherio
Woltan
Registriert: Sa Jan 01, 2005 17:11 Beiträge: 2068
Programmiersprache: C++
Woltan hat geschrieben:
Meine Frage: Erhält hier C.lab wirklich die reference des objektes l? Und was passiert wenn ich das keyword 'var' weglasse. Passiert dann genau dasselbe wie mit?
In dem Fall kann var weggelassen werden. l: TLable ist im Prinzip nur ein typsisierter Pointer auf die Klasse TLable. Somit hast du TLable schon als Reference.
Woltan hat geschrieben:
Kommen wir zu den Pointern: Werden pointer überhaupt noch benutzt? Es gibt das keyword 'unsafe'. Macht es Sinn mit pointern zu arbeiten?
Naja, es gibt Stellen wo man mit Pointern arbeiten muss. Die Frage ist nur ob man allgemeine Pointer oder typisierter (PInteger = ^Integer) benutzt.
Woltan hat geschrieben:
Funktionspointer:
Code:
type
TFunction =function(Integer):Integer;
C =class
func: TFunction;
end;
functionabs(i:Integer):Integer;
begin
if i >=0then
Result := i
else
Result :=-i;
end;
begin
C.func:=@abs;
end;
Man muss nur zwischen Klassenfunkkionen (daher Funktionen die innerhalb einer Klasse definiert sind) sowie allgemeinen Funktionen unterscheiden.
Um mal Missverständnissen vorzubeugen(ja auch bei Dir, iOnOs ): In Delphi herrscht wie auch in C/C++ der Grundsatz CallByValue. Es wird also der Wert des Aufrufparameters in eine lokale Variable kopiert. D.h. der Inhlat der übergebenen Variable ändert sich nicht.
Da aber Instanzvariablen in Delphi ein Doppelleben führen, sind sie implizit Zeiger und werden bei Bedarf implizit dereferenziert. Dies führt dazu, dass bei Objektinstanzen, die übergeben werden sehr wohl die originale Instanz verändert werden kann (kann ich in C ja auch, wenn ich einen Zeiger übergebe). Ich kann quasi Member verändern und der Aufrufer 'merkt' das.
Die übergebene Variable selber ist aber unveränderbar, d.h.ich kann nicht einfach das Objekt freigeben oder Nil zuwesen, da das der Aufrufer nicht mitbekommt (seine Referenz zeigt ins Nirvana). Um dies zu ermöglichen kann ich CallByReference erzwingen, indem ich ein 'var' voanstelle. Tu ich dies, wird auch der Wert der Variable beim Aufrufer verändert.
Weitere Modifikatoren sind noch 'out' und 'const':
'out' signalisiert, dass der Parameter zur Rückgabe dient (Reference). Hier wird sogar ein evtl übergebener Wert gelöscht und steht innerhalb der Funktion nicht zur Verfügung.
'const' bewirkt, dass die übergebene Kopie (Value) innerhalb der Methode nicht veränderbar ist. Es ist quasi zur Konstante geworden und kann weder als Var noch als Out weitergegeben werden.
[edit] Objektinstanzen sind Referenzdatentypen, im Gegensatr zu Wertdatentypen, wie Int oder Char. Das hat mit CallByReference/Value nix zu tun. Die Referenz ist ohne Var sozusagen nicht änderbar, wohl aber das referenzierte Objekt[/edit]
zu Enums: Du kannst neben dem Int-cast auch die Funktion Ord() benutzen. Bei Enums hat der erste immer den Ordinalwert 0, alle weiteren jeweils eins mehr. Rückwärts kommst Du allerdings um den Cast nicht drumrum.
zu Funktionspointern: Offiziell muss in der Deplhilanguage beim Zuweisen ein @ vorangestellt werden, Borland ist hier aber sich selbst untreu geworden und meldet sogar einen Fehler, sodass es eigentlich C.func:=abs; heissen muss. In FPC wird das @ allerdings strikt verlangt (ausser im Delphi-Kompatibilitätsmodus). Klassenmethodentypen werden so definirt:
Einer Variable eines solchen Typs (Normalerweise Ereignisdelegaten) kann man dann nur eine Methode einer Klasseninstanz zuweisen.
_________________ Manchmal sehen Dinge, die wie Dinge aussehen wollen, mehr wie Dinge aus, als Dinge.
<Esmerelda Wetterwax>
Es kann vorkommen, dass die Nachkommen trotz Abkommen mit ihrem Einkommen nicht auskommen und umkommen.
Vielen Dank erstmal für die ausführlichen Erklärungen! Sie haben mir sehr weitergeholfen, und das Projekt an dem ich arbeite nimmt langsam gestallt an. Ich glaube es gilt nur noch ein Delphibezogenes Problem zu lösen. Und das ist jenes:
Code:
Link = class(TObject)
public
myLabel : string;
iArray : integer;
construcot Create(s : string; i : integer);
end;
Link.Create(s : string; i : integer);
myLabel := s; //Hier kommt die exception
iArray := i;
end;
M = class(TObject)
public
constructor Create;
private
var
linkArray : array[0..32] of Label;
end;
M.Create;
var I : integer;
begin
for I := 0 to 32 do linkArray[I].Create('blub', I);
end;
end.
Was mache ich an diesem Beispiel da oben falsch? Warum werden die Elemente von Link nicht mit dem Construktor automatisch allokiert?
Bin für jeden link/tipp dankbar
.. auch hier liegen Delphi und C++ näher beieinander, als man denkt. In C erstellst Du eine Instanz mit
Code:
new Klassenname(Parameter)
an. Es wird sozusagen die Methode der Klasse gerufen, die genauso heisst und diesen Typ zurückgibt. Du würdest in C doch auch nie schreiben
Code:
Klassenname Variable;
new Variable;
In Delphi kann man allerdings seine Konstruktoren nennen, wie man will und deshalb muss hier die Methode mit angegeben werden. Beispiel:
Code:
Type
TFoo=Class(TObject)
public
Constructor MeinKonstrukt;
End;
.....
Constructor TFoo.MeinKonstrukt;
Begin
Inherited Create;
//tu was;
End;
//irgendwo im Code
meineVar:=TFoo.MeinKonstrukt;// legt auch eine Instanz an.
_________________ Manchmal sehen Dinge, die wie Dinge aussehen wollen, mehr wie Dinge aus, als Dinge.
<Esmerelda Wetterwax>
Es kann vorkommen, dass die Nachkommen trotz Abkommen mit ihrem Einkommen nicht auskommen und umkommen.
Mitglieder in diesem Forum: 0 Mitglieder und 11 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.