Thread View: pl.comp.lang.pascal
2 messages
2 total messages
Started by webmajsterek
Sat, 15 Dec 2007 16:48
operator -- i dziwny blad
Author: webmajsterek
Date: Sat, 15 Dec 2007 16:48
Date: Sat, 15 Dec 2007 16:48
44 lines
1715 bytes
1715 bytes
bawie sie operatorami ,
mam cosik takiego
type
Test=class
private
function NumberToDexString:String;virtual;
procedure DexStringToNumber( S:String);virtual;
property DexString : String read NumberToDexString
write DexStringToNumber;
end;
i operator
operator := (A :Test ):String;
begin
Result := A.NumberToDexString;
end;
----------------
teraz jak w proramie
napisze
var T:Test;
T:=Test.Creat......
T.DexSring:='123'; //oki
Memo.Lines.Add(T.DexString);//oki
Memo.Lines.Add(T);//oki
Memo.lines.Add('laczoney lancuch'+T.DexString+' ..');//oki
Memo.lines.Add('laczoney lancuch'+T+' ..');//zonk
jak myslicie to blad kompilatora czy moj ??
--
Wysłano z serwisu OnetNiusy: http://niusy.onet.pl
Re: operator -- i dziwny blad
Author: Wiktor S.
Date: Sun, 16 Dec 2007 23:49
Date: Sun, 16 Dec 2007 23:49
129 lines
4395 bytes
4395 bytes
> operator :=(A:Test):String;
> begin
> Result := A.NumberToDexString;
> end;
> Memo.lines.Add('laczoney lancuch'+T+' ..');//zonk
> jak myslicie to blad kompilatora czy moj ??
Twój. w zapisie 'laczoney lancuch'+T+' ..' nie ma zastosowania operator :=
tylko +
:= jest stosowane tam, gdzie jest jawnie stosowane, albo następuje
przekazanie parametru z niezgodnym typem, np:
------------
procedure costam(s:string); begin {...} end;
var t:test;
costam(t);
------------
ponieważ w tym nawiasie wykonuje się s:=t (gdzie t:test, a s:string) to ma
zastosowanie twój operator.
Niestety, przy operatorach taka automatyczna konwersja nie jest dokonywana
(i jest to przekonywająco uzasadnione w helpie, chodzi o to by uniknąć
niejednoznacznych lub nadmiarowych konwersji).
Trzeba narobić operatorów, do każdej użytecznej kombinacji ;-)
operator +(a:test;b:string):string;
begin
result:=a.numbertodexstring+b;
end;
operator +(a:string;b:test):string;
begin
result:=a+b.numbertodexstring;
end;
operator +(a:test;b:test):string;
begin
result:=a.numbertodexstring+b.numbertodexstring;
end;
musisz zrobić wszystkie trzy przypadki, inaczej przy niektórych wyrażeniach
kompilator ci wyrzuci błąd.
Aha, i bardzo ważne: robisz operatory na klasach, więc pamiętaj o pułapce:
wystrzegaj się operatorów, które zwracają obiekt klasy, np:
-----------
operator +(a:test;b:test):test; // klasa jako wynik - niebezpieczne
begin
...
end;
-----------
taki operator musiałby tworzyć {poprzez .create()} swój wynik:
-----------
operator +(a:test;b:test):test;
begin
result.create;
...
end;
-----------
i testujemy:
-----------
var a,b,c:test;
a:=test.create;
b:=test.create;
c:=a+b;
{...}
a.free;
b.free;
c.free;
-----------
wewnątrz dodawania mamy niejawny konstruktor obiektu c. ALE:
-----------
var a,b,c,d:test;
a:=test.create;
b:=test.create;
c:=test.create;
d:=a+b+c;
{...}
-----------
i? i wszystko niby ok, tylko że podczas wykonywania działania utworzono
tymczasowy obiekt z wynikiem (a+b). Następnie kolejny z wynikiem (a+b)+c, i
ten właśnie jest zwracany jako d. A tamten pośredni? zgubiliśmy - powstał,
nigdy nie został zniszczony i zniszczony być nie już może, bo nie mamy na
niego żadnego wskaźnika. Mamy wyciek w pamięci - a gdyby taki kod (albo
mniej oczywisty, ale z tym samym efektem) pojawił się np. w pętli
wykonującej się 1000 razy na sekundę, posypanie programu gotowe.
Dlatego nie wolno pisać operatorów, w których tworzony jest jakikolwiek
obiekt klasy - bo nie będzie mógł być zniszczony.
Oznacza to, że odpadają operatory zwracające "class", co nas dość mocno
ogranicza. Ale możemy:
- dowoli używać operatorów w przypadku tablic i rekordów (oczywiście jeżeli
nie zawierają klas w sobie)
- dowoli używać operatorów w przypadku obiektów typu "object" (zamiast
"class"). są one przekazywane przez wartość (jak rekordy) i efekt wycieku
pamięci nie wystąpi, ale "object" nie obsługują właściwości (property).
- jeżeli już koniecznie potrzebujesz klasy typu "class", to musisz utworzyć
dodatkowy typ interfejsowy (interface), a klasę dziedziczyć po
TIterfacedObject. Da ci to automagiczne wywoływanie destruktora na takim
tymczasowym obiekcie, jak wyżej opisałem. Jeśli chcesz szczegółów, służę
pomocą ;-)
--
Azarien
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads