Rekordy, metody(constructor, destructor) ?

Rekordy, metody(constructor, destructor) ?
DJ
  • Rejestracja:prawie 21 lat
  • Ostatnio:około 15 lat
  • Postów:186
0

Witam!

Niestety jakiś czas nie działa mi pomoc do Turbo Delphi i nie moge z niej skożystać. Poszukiwałem także na sieci ale bez większego powodzenia.

Problem:
Czy można zdeklarowac konstruktor i destruktor dla rekordu. Dla object i class nie ma problemu. Znalazłem że można użyć następującej konstrukcji class constructor Create ... ale mój kompilator twierdzi że tak nie można. Interesuje mnie to z tego powodu iż dla rekordów mogę przeładować operatory a dla klas nie zabardzo(Win32). Jeżeli macie jakieś informacje na ten temat to proszę o ich udostępnienie na forum.

PS. Bardziej interesuje mnie destruktor aniżeli konstruktor poniewarz operatory przypisane do rekordu podczas działania zmieniają długośćdynamicznej tablicy będącej jednym z pól rekordu, i przy kończeniu danego podprogramu gdy rekord znika z pamięci zaalokowana pamięć na tablice nie zostaje zwalniana.

Gdyby istniała taka możliwość rzczony rekord wraz z operatorami zystał by funkcjonalność zbliżoną do systemowego String'a, a niestety bez tego mechanizmu, tracimy na wygodzie, a przy dłuższym działaniu programu możliwe będzie zassanie sporej iności pamięci(oczywiście zakładając że nie będzie się jej zwalniać ręcznie)


Great spirits have always encountered violent opposition from mediocre minds.
_Nex_
  • Rejestracja:około 19 lat
  • Ostatnio:ponad 15 lat
  • Postów:507
0

Wydaje mi się że w wypadku rekordów konieczne jest samodzielne zwalnianie po nich pamięci... Ale głowy nie dam. ;)


Program to zbiór zer i jedynek ułożonych tak, żeby denerwować użytkownika.
SZ
  • Rejestracja:ponad 21 lat
  • Ostatnio:ponad 15 lat
  • Postów:3356
0

Nie ma możliwości zdefiniowania konstruktora/destruktora dla rekordu. Kończy się to błędem: [Pascal Error] E2465 A record cannot introduce a destructor

Ewentualnie strukturę tą możesz opakować jako pole pewnej klasy, ale lekko utraci to swoją 'przezroczystość' użycia.


Dzięki wszystkim forumowiczom za lata wspólnych dyskusji; miłej zabawy w programowanie!
Sławomir "Szczawik" Włodkowski
DJ
  • Rejestracja:prawie 21 lat
  • Ostatnio:około 15 lat
  • Postów:186
0

Właśnie że rekord zwalania się sam tylko, że ja mam taki rekord

Kopiuj
Jakiś_Rekord = record
  ...
  Data: array of Integer;
end;

i po wykonaniu podprogramu gdy wszystkie zmienne danego typu są usuwane ze stosu pozostaje niezwolniona pamięć po Data jeżeli nie było nil;

Było by bardzo fanie bdyby delphi pozwalało budować takie typy jak systemowy String, który w funkcjonalności defakto jest znacznie bardziej skomplikowany niż rekord z przeciążaniem operatorów(no ale cóż). Hm pomimo faktu zprowadzenia przeciązania operatorów, borland w żadnym z plików w dystrybucji Turbo Delphi ne używa operatorów


Great spirits have always encountered violent opposition from mediocre minds.
DJ
  • Rejestracja:prawie 21 lat
  • Ostatnio:około 15 lat
  • Postów:186
0

Ok znalazłem pod adresem http://delphi.about.com/od/adptips2006/qt/newdelphirecord.htm i rzczywiście jest taka możliwość ale od Delphi 2006 :( a szkoda


Great spirits have always encountered violent opposition from mediocre minds.
_Nex_
  • Rejestracja:około 19 lat
  • Ostatnio:ponad 15 lat
  • Postów:507
0
dj napisał(a)

Ok znalazłem pod adresem http://delphi.about.com/od/adptips2006/qt/newdelphirecord.htm i rzczywiście jest taka możliwość ale od Delphi 2006 :( a szkoda

Ciekawe.. :) A dlaczego szkoda? Turbo Delphi to właśnie D2k6, tylko TROSZKĘ okrojone. Więc powinno działać.


Program to zbiór zer i jedynek ułożonych tak, żeby denerwować użytkownika.
LU
  • Rejestracja:ponad 19 lat
  • Ostatnio:około 11 lat
0

O ile mi wiadomo tablice dynamiczne nie są umieszczane na stosie (a jedynie wskaźnik do nich) i zarządzane są automatycznie (cokolwiek to znaczy), podobnie jak długie stringi

Oleksy_Adam
  • Rejestracja:prawie 19 lat
  • Ostatnio:ponad 11 lat
0

Proponuję przeanalizować przykład Demos\DelphiWin32\VCLWin32\ComplexNumbers

Kopiuj
type
  TComplex = packed record{$IFDEF CIL}(IComparable, IConvertible){$ENDIF}
  strict private
  // No record class constructors in Win32 (yet)
{$IFDEF CIL}    class constructor Create; {$ENDIF}
    procedure Defuzz;
  private
    class procedure Init; static;
  public
    var
      Real, Imaginary: Double;
    class var
      Symbol: string;                 // defaults to 'i'
      SymbolBeforeImaginary: Boolean; // defaults to false
      DefuzzAtZero: Boolean;          // defaults to true

    class function From(const AReal: Double): TComplex; overload; static;
    class function From(const AReal, AImaginary: Double): TComplex; overload; static;
{$IFDEF CIL}
    class function FromObject(AObject: TObject): TComplex; static;
{$ENDIF}

    class function FromPolar(const AModulus, APhase: Double): TComplex; static;
    function Modulus: Double;
    function Phase: Double;
// (...)

<span style="color: blue">"Kolarstwo to jedna z najtrudniejszych dyscyplin sportu. Nawet najgorszy kolarz jest wciąż wybitnym sportowcem."
s.p. Marco Pantani
</span>
DJ
  • Rejestracja:prawie 21 lat
  • Ostatnio:około 15 lat
  • Postów:186
0

Ok dzięki Oleksy_Adam za czynk o tym TComplex

dzięki niemu mam warzną wskazówkę

// No record class constructors in Win32 (yet)
{$IFDEF CIL} class constructor Create; {$ENDIF}

ale przebadałem sprawe dokładniej bo program nadal pokazywał przecieki pamięci

aktualnie mam coś takiego :

Kopiuj
...
var
  a, b, c, d, s, g: BigInteger;

begin
  System.ReportMemoryLeaksOnShutdown:= True;

  a:= 1;
  b:= 2;
  s:= 40550;
  g:= -s;
  g:= g * 50;
  dec(g);

  Writeln(IntToStr(LongValue(s)));

  _BigIntClr(a);
  _BigIntClr(b);
  _BigIntClr(c);
  _BigIntClr(d);
  _BigIntClr(s);
  _BigIntClr(g);

  Writeln('  Alokowano pamiec: ', BigInts.me_alloc);
  Writeln('ReAlokowano pamiec: ', BigInts.re_alloc);
  Writeln('DeAlokowano pamiec: ', BigInts.de_alloc);

  Readln;
end.

Dodałem liczniki które każdorazowo liczą ilości alokowania, realokowania, dealokowania pamięci na dynamiczną tablice w BigInteger
i po tym całym procesie me_alloc = de_alloc a jednak dostaje raport o przeciekach, jak myślicie co może powodować takie zachowanie.

Ciekawostka po zakomentowaniu _BigIntClr(...); liczba de_alloc zmniejsza się ale wskazania przecieków pozostają takie same.

Zrobiłem także eksperymęt i za każdym razem alokowałem o 10 elementów więcej w tablicy i w tym momęcie wskazania przecieków zwiększyły się aczkolwiej nie zwiekszyła sie ich ilość


Great spirits have always encountered violent opposition from mediocre minds.
Marmar
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 2 lata
  • Postów:317
0

Witam
Chyba dobrze byłoby gdybyś pokazał więcej kodu. W szczególności co się dzieje podczas przypisania ":=" i działań, ktore są w tym przykładzie.
Swoją drogą to nie sądzicie, że to dziwne zachowanie borlanda ze wspieraniem recordów i to w tak połowiczny sposób? Jest konstruktor nie ma destruktora, konstruktor jest ale nie niezbędny, operatory można przeciążać tu a w klasach nie. O co tu chodzi? :)
BTW co to za moduł system, w ktorym jest coś takiego jak ReportMemoryLeaksOnShutdown?

DJ
  • Rejestracja:prawie 21 lat
  • Ostatnio:około 15 lat
  • Postów:186
0

ReportMemoryLeaksOnShutdown to zmienna typu Boolean w systemowy module dodawanym do każdego kompilowanego programu. Ustawienie tego na true powoduje że po zakończeniu aplikacji Memory Manager powoduje wypisanie niezwolnionej pamięci.

Hm: trochę kodu prosze bardzo:

Kopiuj
 BigInteger = record
  private
    Ref: Integer;
    Sign: Integer; // wartości dodatani lub ujemna
    Data: array of Cardinal;
  public
    class operator Implicit(Value: Int64): BigInteger;
    class operator Implicit(Value: BigInteger): BigInteger;
    class operator Implicit(Value: String): BigInteger;
    ...
  end;


class operator BigInteger.Implicit(Value: Int64): BigInteger;
begin
  NewBigInteger(Result, Value);
end;

_________________________________________________

procedure _FreeBigInt(var a: BigInteger);
begin
  if a.Data <> nil then begin
     a.Data:= nil; // Zwalanianie
     Inc(de_alloc);
  end;
  a.Ref:= 0;
end;

procedure _BigIntClr(var S);
var
  a: BigInteger;
begin
  if Pointer(S) <> nil then begin
     a:= BigInteger(S);
     Pointer(S):= nil;
     if a.Ref > 0 then
        if InterlockedDecrement(a.Ref) = 0 then begin
           if a.Data <> nil then begin
              a.Data:= nil; // Zwalnianie
              inc(de_alloc);
           end;
        end;
  end;
end;


procedure NewBILen(var a: BigInteger; Length: Longint);
begin
  if Length <= 0 then
     Exit;
  _BigIntClr(a);

  if a.Data = nil then
     inc(me_alloc)
  else
     inc(re_alloc);

  SetLength(a.Data, Length);
  FillChar(a.Data[0], Length, 0);
  a.Sign:= 0;
  a.Ref:= 1;
end;

procedure NewBigInteger(var a: BigInteger; i: Int64);
begin
  _FreeBigInt(a);
  if Int64Rec(i).Hi = 0 then begin
     NewBILen(a, 1);
     a.Data[0]:= Int64Rec(i).Lo;
     a.Sign:= 1;
  end else begin
     NewBILen(a, 2);
     a.Data[0]:= Int64Rec(i).Hi;
     a.Data[1]:= Int64Rec(i).Lo;
     a.Sign:= 2;
  end;
  if i < 0 then
     a.Sign:= -a.Sign;
end;

Z tego wynika że definicja Implicit nie odpowiada za pewne rzeczy
i rzeczywiście tak jest po wejrzeniu w CPU(disasembler) widać że po wykonaniu kodu operatora wywoływany jest
call @CopyRecord
czyli systemowa funkcja odpowiadająca za kopiowanie rekordu.

Ciekawostka:
jeżeli wywołujemy s:= s1; i obie zmienne są typu String
wywoływana jest procedure _LStrAsg(var dest; const source); co daje znacznie wieksze możliwości niż operatory Implict w takiej postaci jakie są teraz.


Great spirits have always encountered violent opposition from mediocre minds.
SA
  • Rejestracja:ponad 18 lat
  • Ostatnio:ponad 15 lat
0

Zmien funkcje _BigIntClr tak ja ponizej i dodaj typ wskaznikowy do rekordy BigInteger.

Kopiuj
procedure _BigIntClr(var S);
var a: pBigInteger;
begin
  if @S <> nil then
  begin
     a := @s;
     if a.Ref > 0 then
        if InterlockedDecrement(a.Ref) = 0 then
        begin
           if a.Data <> nil then
           begin
              a.Data:= nil; // Zwalnianie
              inc(de_alloc);
           end;
        end;
  end;
end;

To powinno dzialac bo jak sam powiedziales ze gdy przypisujesz jeden rekord do drugiego to zostaje wywolana funkcja CopyRecord takze za kazdym razem gdy chciales uwolnic pamiec z rekordu to najpier powielales go i po tym uwalniales powielony rekord nie ten z parametru. :).

Kopiuj
procedure _BigIntClr(var S);
var
  a: BigInteger;
begin
  if Pointer(S) <> nil then begin
     a:= BigInteger(S); // tutaj rekord zostaje powielony a powinien to byc adres pamieci do niego
     Pointer(S):= nil; //to linie wtedy trzeba usunac 
     if a.Ref > 0 then
        if InterlockedDecrement(a.Ref) = 0 then begin
           if a.Data <> nil then begin
              a.Data:= nil; // Zwalnianie
              inc(de_alloc);
           end;
        end;
  end;
end;
DJ
  • Rejestracja:prawie 21 lat
  • Ostatnio:około 15 lat
  • Postów:186
0

No jak ja to mgłem przegapić :) Wielkie dzięki sasio :)


Great spirits have always encountered violent opposition from mediocre minds.
SA
  • Rejestracja:ponad 18 lat
  • Ostatnio:ponad 15 lat
0

NIE MA sprawy po to tu wszyscy jestesmy :)

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)