eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.comp.programming › [c++]Prosta klasa, czemu nie wywołuje destruktorów?
Ilość wypowiedzi w tym wątku: 11

  • 11. Data: 2009-08-02 12:09:39
    Temat: Re: [c++]Prosta klasa, czemu nie wywołuje destruktorów?
    Od: Bronek Kozicki <b...@s...net>

    P.K.D wrote:
    > Tutaj ta klasa: http://paste.dprogramming.com/dpibqklz
    >
    > Chodzi o to, że gdy wywołuję server::clearList() to obiekty nie są
    > niszczone, chyba dlatego, że lista zawiera wskaźniki. Jak to zrobić i
    > czy da się zrobić tak, że destruktory będą wywoływane automatycznie?

    1. żeby wiedzieć kiedy będą wołane destruktory, najlepiej polegać na
    jakimś sprytnym wskaźniku oraz wiedzieć kto kiedy jest właścicielem
    obiektu. Poniżej stosuję boost::shared_ptr (bo bardziej popularny i
    obsługuje klasy niekompletne), ale równie dobrze możesz stosować coś
    innego. "dzielenie własności" wbrew nazwie "shared" jest tutaj potrzebne
    tylko do zapewnienia semantyki płytkiego kopiowania i do niczego więcej
    - boost::intrusive_ptr czy własne wynalazki w tej roli też się sprawdzą.

    2. skoro już masz zagwarantowane wyłanie destruktora, to martw się o
    notyfikację obiektu który trzyma listę obiektów żeby je z tej listy
    skasował. Ja korzystam z funkcji UnregisterMyClass wołanej z
    destruktora. Jedyny wyjątek kiedy tego nie trzeba robić - wtedy kiedy
    lista jest i tak w całości kasowana. Oczywiście "lista" jest umowna -
    rownie dobrze może być mapa albo jakaś własna, bardziej złożona
    struktora. Ja w przykładzie niżej korzystam z std::list , dla zachowania
    jasności.

    3. do tego wszystkiego idealnie pasuje Pimpl, bo daje tanią samantykę
    kopiowania i jednoznaczną własność wskaźnika. Jeżeli nie wiesz co to
    jest : http://www.gotw.ca/publications/mill04.htm

    Poniżej przykładowy kod.


    // creator.hpp

    class MyClass
    {
    class Impl;
    boost::shared_ptr<Impl> pimpl_;

    // zwiększamy ekapsulacje ograniczajac dostep do c-tora
    friend class Creator;
    explicit MyClass (boost::shared_ptr<Impl> p) : pimpl_(p) {}

    public:
    // opcjonalnie takie dwie funkcje, jeżeli potrzebne
    void Unregister();
    bool IsRegistered() const;

    // dalej typowy Pimpl
    // ...
    };

    class Creator
    {
    // zwiekszamy enkapsulacje ograniczajac dostep do UnregisterMyClass
    friend class MyClass;
    void UnregisterMyClass(const MyClass::Impl& my);

    std::list<const MyClass::Impl*> myclassobjects_;
    // ... może być więcej podobnych kolekcji ...

    public:
    ~Creator();

    MyClass MakeMyClass(parametry konstruktora);

    // ...
    };


    // creator.cpp
    #include "creator.hpp"

    class MyClass::Impl : public IMogeSobieDziedziczycCokolwiek
    // noncopyable - bo nie obiecujemy więcej niż musimy zaimplementować
    , boost::noncopyable
    {
    Creator& creator_;
    bool registered_;
    // ...

    public:
    Impl(Creator& c, parametry konstruktora)
    : creator_(c)
    , registered_(true)
    // ... inicjalizacja innych pól, definicja konstruktora

    ~Impl() {Release(true);}

    void Release(bool unregister)
    {
    if (unregister && registered_)
    {
    creator_.UnregisterMyClass(*this);
    registered_ = false;
    }
    }

    // opcjonalnie takie dwie funkcje
    void Unregister() {Release(true);}
    bool IsRegistered() const {return registered_;}

    // dalej typowy Pimpl
    // ...
    };

    bool MyClass::IsRegistered() const {return pimpl_->IsRegistered();}
    void MyClass::Unregister() {pimpl_->Unregister();}

    // dalej typowy Pimpl, tzn podobnie jak IsRegistered i Unregister
    // ...
    // ...

    // zarządzanie kolekcja obiektów MyClass przez klasę Creator :

    void Creator::UnregisterMyClass(const MyClass::Impl& my)
    {
    myclassobjects_.remove(&my);
    };

    MyClass Creator::MakeMyClass(parametry konstruktora)
    {
    boost::shared_ptr<MyClass::Impl> p(new MyClass::Impl(*this,
    parametry konstruktora));

    // Nie trzymamy MyClass::Impl na własność - przekazujemy do MyClass !
    myclassobjects_.push_back(p.get());
    return MyClass(p);
    }

    Creator::~Creator()
    {
    // Kazemy obiektom MyClass::Impl sie "zwolnić", zeby oszczędzić
    // wołanie UnregisterMyClass z destruktorów
    std::for_each(myclassobjects_.begin(), myclassobjects_.end(),
    boost::bind(&MyClass::Impl::Release, _1, false));

    myclassobjects_.clear();
    }


    I jeszcze jedna uwaga - NIE NADUŻYWAĆ , bo nie jest wcale takie proste.
    Ale jest za to dosyć niezawodne - jeżeli potrzebujemy mieć kolekcję
    obiektów które skonstruowaliśmy.



    B.


    --
    Remove -trap- when replying. Usun -trap- gdy odpisujesz.

strony : 1 . [ 2 ]


Szukaj w grupach

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: