b'\n_START_ARTICLE_\nDestruktor\n_START_SECTION_\nPrzyk\xc5\x82adowy destruktor\n_START_PARAGRAPH_\nW sk\xc5\x82adni C++:_NEWLINE__NEWLINE_  class Samochod{_NEWLINE_    public:_NEWLINE_      string marka;_NEWLINE_      //... (pewne dane i metody)_NEWLINE_      ~Samochod() {_NEWLINE_        std::cout << "Samochod " << marka << " zostal usuniety.\\n";_NEWLINE_      }_NEWLINE_  };_NEWLINE_Tu destruktorem jest ~Samochod(). W chwili usuwania obiektu, dok\xc5\x82adnie przed zwolnieniem pami\xc4\x99ci przeznaczonej dla obiektu jest wywo\xc5\x82ywany destruktor - st\xc4\x85d te\xc5\xbc podczas usuwania danego samochodu zostanie wy\xc5\x9bwietlona linijka tekstu informuj\xc4\x85ca o tym. Warto zwr\xc3\xb3ci\xc4\x87 uwag\xc4\x99, \xc5\xbce powy\xc5\xbcszy przyk\xc5\x82ad jest nieco sztuczny - destruktor takiej postaci nie jest b\xc5\x82\xc4\x99dny, ale w rzeczywistych programach (poza momentem testowania powo\xc5\x82ywania i niszczenia obiekt\xc3\xb3w) nie stosuje si\xc4\x99 destruktor\xc3\xb3w do drukowania komunikat\xc3\xb3w na ekranie.\n_START_SECTION_\nDestruktor a wyciek pami\xc4\x99ci\n_START_PARAGRAPH_\nWa\xc5\xbcnym zadaniem destruktora jest usuwanie podleg\xc5\x82ych obiekt\xc3\xb3w dynamicznych, kt\xc3\xb3re s\xc4\x85 mu przydzielone. Je\xc5\xbceli nie zostan\xc4\x85 one zwolnione w destruktorze, to dojdzie do tzw. wycieku pami\xc4\x99ci. Poni\xc5\xbcej przedstawiony zosta\xc5\x82 przyk\xc5\x82ad klasy w C++, gdzie brak destruktora spowodowa\xc5\x82by wyciek:_NEWLINE__NEWLINE_  class MojaKlasa _NEWLINE_  {_NEWLINE_    public:_NEWLINE_      MojaKlasa()_NEWLINE_        : liczba(new int) _NEWLINE_      {_NEWLINE_        *liczba = 0;_NEWLINE_      }_NEWLINE_      ~MojaKlasa() _NEWLINE_      {_NEWLINE_        delete liczba;_NEWLINE_      }_NEWLINE_    private:_NEWLINE_      int *liczba;_NEWLINE_  };_NEWLINE_Brak destruktora w tym przypadku spowoduje, \xc5\xbce zostanie zwolniona pami\xc4\x99\xc4\x87 przeznaczona na obiekt, w kt\xc3\xb3rym jest mi\xc4\x99dzy innymi wska\xc5\xbanik liczba, ale nie zostanie zwolniona pami\xc4\x99\xc4\x87 na kt\xc3\xb3r\xc4\x85 wskazuje liczba, poniewa\xc5\xbc ten adres w pami\xc4\x99ci nie zawiera si\xc4\x99 obszarze pami\xc4\x99ci zajmowanej przez obiekt klasy MojaKlasa. Domy\xc5\x9blna implementacja destruktura nie jest w przypadku klasy MojaKlasa wystarczaj\xc4\x85ca do prawid\xc5\x82owego usuni\xc4\x99cia zaalokowanej pami\xc4\x99ci._NEWLINE_Powy\xc5\xbcszy przyk\xc5\x82ad nie jest kompletn\xc4\x85 klas\xc4\x85, kt\xc3\xb3ra dzia\xc5\x82a\xc5\x82aby prawid\xc5\x82owo w j\xc4\x99zyku C++, gdy\xc5\xbc brak jest konstruktora kopiuj\xc4\x85cego i operatora przypisania. Pomini\xc4\x99to je ze wzgl\xc4\x99du na czytelno\xc5\x9b\xc4\x87 przyk\xc5\x82adu.\n_START_SECTION_\nWirtualny destruktor\n_START_PARAGRAPH_\nW wi\xc4\x99kszo\xc5\x9bci j\xc4\x99zyk\xc3\xb3w destruktor, tak jak ka\xc5\xbcda metoda mo\xc5\xbce by\xc4\x87 wirtualny. W wielu sytuacjach destruktor musi by\xc4\x87 wirtualny aby zapewni\xc4\x87 prawid\xc5\x82owe wykorzystanie klasy, np. w C++ klasa powinna mie\xc4\x87 destruktor wirtualny kiedy zachodzi mo\xc5\xbcliwo\xc5\x9b\xc4\x87, \xc5\xbce inna klasa b\xc4\x99dzie po niej dziedziczy\xc5\x82a i b\xc4\x99dzie u\xc5\xbcywany polimorfizm. Jest to mo\xc5\xbcliwo\xc5\x9b\xc4\x87 dziedziczenia, nawet kiedy w danej chwili klasa nie ma \xc5\xbcadnych potomk\xc3\xb3w; w przeciwnym razie zachodzi konieczno\xc5\x9b\xc4\x87 zmiany deklaracji destruktora w momencie dodania klasy pochodnej, a to spowodowa\xc5\x82oby zerwanie kompatybilno\xc5\x9bci z ju\xc5\xbc istniej\xc4\x85cym kodem wykorzystuj\xc4\x85cym t\xc4\x99 klas\xc4\x99.\n_START_SECTION_\nPrzyk\xc5\x82ad w C++\n_START_PARAGRAPH_\n#include <iostream>class Osoba{_NEWLINE_   public:_NEWLINE_      virtual ~Osoba()_NEWLINE_      {_NEWLINE_         std::cout << "~Osoba(): uruchomiono" << std::endl;_NEWLINE_      }};class Pracownik : public Osoba{_NEWLINE_   public:_NEWLINE_      ~Pracownik()_NEWLINE_      {_NEWLINE_         std::cout << "~Pracownik(): uruchomiono" << std::endl;_NEWLINE_      }};int main(){_NEWLINE_   Osoba *wsk = new Pracownik;_NEWLINE_   delete wsk;_NEWLINE__NEWLINE_   return 0;}_NEWLINE_W powy\xc5\xbcszym przyk\xc5\x82adzie zosta\xc5\x82y zdefiniowane dwie klasy - klasa podstawowa Osoba oraz klasa pochodna Pracownik. W sekcji publicznej klasy Osoba zosta\xc5\x82 zdefiniowany wirtualny destruktor. Ma to istotne znaczenie w przypadku wykorzystywania polimorfizmu._NEWLINE_W funkcji g\xc5\x82\xc3\xb3wnej main() zostaje zdefiniowany wska\xc5\xbanik typu Osoba, kt\xc3\xb3remu zostaje przypisany adres obiektu typu Pracownik zdefiniowanego dynamicznie. Poprzez wykorzystanie operatora delete, kt\xc3\xb3ry usuwa z pami\xc4\x99ci wcze\xc5\x9bniej utworzony obiekt typu Pracownik, zostaje wywo\xc5\x82any niejawnie destruktor klasy Pracownik._NEWLINE_Wynikiem dzia\xc5\x82ania programu b\xc4\x99dzie wypisanie na ekranie:_NEWLINE__NEWLINE_~Pracownik(): uruchomiono_NEWLINE_~Osoba(): uruchomiono_NEWLINE_W przypadku pomini\xc4\x99cia s\xc5\x82owa virtual przed definicj\xc4\x85 destruktora w klasie Osoba, destruktor ~Pracownik() nie zosta\xc5\x82by wywo\xc5\x82any, poniewa\xc5\xbc kompilator uzna\xc5\x82by, \xc5\xbce pokazuje na obiekt typu Osoba (nie zosta\xc5\x82by sprawdzony typ obiektu, na kt\xc3\xb3ry pokazuje wska\xc5\xbanik, w trakcie dzia\xc5\x82ania programu)._NEWLINE_Pomini\xc4\x99cie wywo\xc5\x82ania destruktora klasy pochodnej mo\xc5\xbce doprowadzi\xc4\x87 do powa\xc5\xbcnych b\xc5\x82\xc4\x99d\xc3\xb3w w dzia\xc5\x82aniu programu np. do wycieku pami\xc4\x99ci. Oczywi\xc5\x9bcie w tym prostym przyk\xc5\x82adzie nie doprowadzi to do \xc5\xbcadnych powa\xc5\xbcnych konsekwencji. W przypadku niekorzystania z polimorfizmu, nie ma to znaczenia._NEWLINE_Destruktor klas dla kt\xc3\xb3rych tworzy si\xc4\x99 klasy potomne musz\xc4\x85 mie\xc4\x87 destruktor wirtualny. Ka\xc5\xbcda kolejna klasa, kt\xc3\xb3ra dziedziczy od klasy potomnej, kt\xc3\xb3rej rodzic ma destruktor wirtualny, r\xc3\xb3wnie\xc5\xbc b\xc4\x99dzie posiada\xc5\x82a destruktor wirtualny, nawet gdy nie u\xc5\xbcyjemy virtual przy deklaracji czy definicji destruktora w klasie._NEWLINE_Oznacza to, \xc5\xbce gdyby dopisa\xc4\x87 do powy\xc5\xbcszego przyk\xc5\x82adu:_NEWLINE_(...)class Elektryk : public Pracownik{_NEWLINE_   public:_NEWLINE_      ~Elektryk()_NEWLINE_      {_NEWLINE_         std::cout << "~Elektryk(): uruchomiono" << std::endl;_NEWLINE_      }};_NEWLINE_ _NEWLINE_int main(){_NEWLINE_   Osoba *wsk = new Elektryk;_NEWLINE_   delete wsk;_NEWLINE_ _NEWLINE_   return 0;}_NEWLINE_to wynikiem dzia\xc5\x82ania programu b\xc4\x99dzie wypisanie na ekranie:_NEWLINE__NEWLINE_~Elektryk(): uruchomiono_NEWLINE_~Pracownik(): uruchomiono_NEWLINE_~Osoba(): uruchomiono_NEWLINE_natomiast w przypadku pomini\xc4\x99cia virtual w klasie podstawowej, wywo\xc5\x82anie wszystkich destruktor\xc3\xb3w (poza destruktorem klasy Osoba) zostanie pomini\xc4\x99te i na ekranie b\xc4\x99dzie wypisane tylko:_NEWLINE__NEWLINE_~Osoba(): uruchomiono\n_START_SECTION_\nFinalizator\n_START_PARAGRAPH_\nW niekt\xc3\xb3rych j\xc4\x99zykach z wbudowanym od\xc5\x9bmiecaczem (np. Java i C#) dost\xc4\x99pna jest sk\xc5\x82adnia finalizatora - specjalnej metody wywo\xc5\x82ywanej, gdy obiekt jest usuwany przy od\xc5\x9bmiecaniu. W przeciwie\xc5\x84stwie do destruktora nie wiadomo, w kt\xc3\xb3rym dok\xc5\x82adnie momencie dzia\xc5\x82ania programu to nast\xc4\x85pi.'