🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.lang.pascal
2 messages
2 total messages Started by webmajsterek Sat, 15 Dec 2007 16:48
operator -- i dziwny blad
#92323
Author: webmajsterek
Date: Sat, 15 Dec 2007 16:48
44 lines
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
#92324
Author: Wiktor S.
Date: Sun, 16 Dec 2007 23:49
129 lines
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