przece tiążenie operatorów w fcp 2.2.4

0

witam

mam za zadanie napisać w pascalu bibliotekę do rachunku zespolonego. aby to miało ręce i nogi postanowiłem zrobić to na przeciążonych operatorach i jednej klasie. i mam problem bo gdy piszę funkcję

operator = (wej1 : complex; wej2 : typ) wyj : boolean;
        begin
        if (wej1.re = wej2) and (wej1.im = 0) then wyj := true else wyj := false;
        end;

to wywala mi błąd kompilacji: impossible operator overload a identyczna funkcja jest na stronie Free Pascal :
Reference guide http://www.freepascal.org/docs-html/ref/ref.html tylko że na typie a nie na klasie. co dziwne przeciążenie takich operatorów jak +, -, * nie sprawia problemu a głupie porównanie tak.

więc mam pytanie: co robię nie tak i czy w ogóle da się przeciążyć w fpc operator porównania na klasach?

0

W Pascalu przeciążenie operatora = dla klas jest niemożliwe. Dwa obiekty są równe wtedy i tylko wtedy gdy wskazują na tę samą instancję. Tego zachowania nie da się zmienić. Możesz albo przerzucić się na rekordy, albo zrobić funkcję na wzór języka C#

function complex.Equals(a:complex):boolean;
begin
  Equals:=(re=a.re) and (im=a.im);
end;

Nie chcę ci spalać roboty, ale wykonujesz pracę nadmiarową, bo typ complex jest już gotowy ze wszystkimi operatorami (unit ucomplex), zrobiony nie na klasie a na rekordzie.

Być może nie jesteś świadomy jeszcze jednej rzeczy: przypisanie a:=b dla klas nie oznacza skopiowania obiektu, a jedynie referencji, np:

{$mode objfpc}
type complex=class re,im:real end;
var a,b:complex;
begin
  a:=complex.create;
  a.re:=5;
  a.im:=10;
  b:=a;
  writeln(b.re,' ',b.im); // wypisuje 5 10 - ok
  a.re:=9;
  writeln(b.re,' ',b.im); // wypisuje 9 10, a przecież modyfikowaliśmy obiekt a!
  a.free;
end.

W ogóle rekord bardziej się do tego nadaje: nie trzeba go tworzyć ani niszczyć, można przeciążać równość, a przypisanie kopiuje zmienną a nie tworzy nową referencję. Ale - jak już powiedziałem - jest to już w pakiecie:

uses ucomplex;

var z:complex;
begin
  z.re:=5;
  z.im:=2.5;
end.

Przeciążanie operatorów arytmetycznych dla klas wiąże się też z ryzykiem
wycieków pamięci, np: w przykładzie a:=b+c+d tworzymy nowy obiekt (nazwijmy go tmp) o wartości b+c, potem tworzymy drugi obiekt o wartości tmp+d i przypisujemy go do zmiennej a. Referencja do obiektu tmp została utracona, a ponieważ we FreePascalu obiekty nie są automatycznie niszczone, pamięć zaalokowana na ten obiekt jest stracona (zgubiona). Jest na to obejście, ale wykracza poza ten post :-)

0

witam

dzięki za odpowiedź.

napisanie takiego unita to nie mój wymysł tylko zadanie na zaliczenie :)
chciałem zrobić to na klasie aby od razu po wykonaniu a.re := 5 przeliczane było fi. moja klasa na także właściwość moduł i fi. widzę że klasą nie skrócę sobie roboty więc przerzucę się na typ obiektowy. mam nadzieje że nie wykazuje on takich właściwości przy przypisaniu jak klasa.

i jeszcze jedno pytanie. jeśli przypiszę a do b a potem wykonam a.free to co się stanie z b?

0
kaszti napisał(a)

napisanie takiego unita to nie mój wymysł tylko zadanie na zaliczenie :)

Ja rozumiem.

chciałem zrobić to na klasie aby od razu po wykonaniu a.re := 5 przeliczane było fi.

Automatycznie? Wtedy re musiałoby być właściwością (property), a…

widzę że klasą nie skrócę sobie roboty więc przerzucę się na typ obiektowy. mam nadzieje że nie wykazuje on takich właściwości przy przypisaniu jak klasa.

…zmienne "object" co prawda zachowują się jak rekordy a nie jak klasy, ale nie ma w nich property.

i jeszcze jedno pytanie. jeśli przypiszę a do b a potem wykonam a.free to co się stanie z b?

b po przypisaniu b:=a znaczy to samo co a (nie jest równe, tylko JEST TYM SAMYM). Więc czy zrobisz a.free czy b.free to to jedno i to samo.
Zauważ, że unikam zdania "b jest też niszczone", bo tu nie ma żadnego "też". Obiekt w pamięci jest jeden, o dwóch równoważnych nazwach: a i b.
Odwołanie się do b po zniszczeniu a spowoduje wywalenie się programu.

0

co prawda nigdzie nie znalazłem informacji sugerującej że typ obiektowy ma property ale postanowiłem sprawdzić i co najdziwniejsze działa to:). zresztą zauważyłem że fpc ma trochę luźne podejście do niektórych spraw. udało mi się zmienić wartość const i przekroczyć wartość typu ograniczonego. co najwyżej kompilator dał mi ostrzeżenie.

0

sorry że post pod postem ale nie jestem zarejestrowany.

mam 2 pytania za 100p.

czy w fpc dyrektywy public i private to w ogóle działają?

i czy jak mam właściwość np. cstr konwertującą ze stringa do zespolonej i na odwrót to czy jakoś mogę ją zmusić aby działało readln(a.cstr) bo jak na razie działami tylko readln(sss); a.cstr := sss;

0

Składnia FPC się niestety obecnie ostro rozjeżdża z najnowszymi wydaniami Delphi - obie strony wymyślają swoje rozszerzenia, czasami nawet to samo ale inaczej.

Tak, dyrektywy public i private jak najbardziej działają, ale pod warunkiem że odwołujesz się do typu zadeklarowanego w innym unicie. W ramach tego samego pliku "private" nie działa. Nigdy nie działało ;-)
Możesz spróbować "strict private", ale nie wiem w tej chwili, czy FPC go obsługuje (patrz wyżej).

Nie, nie da się nauczyć readln/writeln żeby przyjmowało nasz typ.

1 użytkowników online, w tym zalogowanych: 0, gości: 1