Yıkıcıya özel olarak sahip olmanın faydası nedir?


Yanıtlar:


177

Temel olarak, başka bir sınıfın sınıfınızın nesnelerinin yaşam döngüsünden sorumlu olmasını istediğinizde veya bir nesnenin yok edilmesini önlemek için nedeniniz olduğunda, yıkıcıyı özel yapabilirsiniz.

Örneğin, bir çeşit referans sayma işi yapıyorsanız, kendisine referans sayısını saymaktan ve sayı sıfıra çarptığında onu silmek için nesnenin (veya "arkadaş" tarafından düzenlenmiş yöneticinin) sorumlu olmasını sağlayabilirsiniz. Özel bir dtor, hala referanslar olduğunda başkalarının onu silmesini önleyecektir.

Başka bir örnekte, yöneticinin (veya kendisinin) yok edebileceği veya program bağlantısının açık olması veya bir dosya yazılması gibi programdaki diğer koşullara bağlı olarak onu yok edebilecek bir nesneniz varsa ne olur? Sınıfta veya yöneticide bu koşulu kontrol edecek bir "request_delete" yöntemine sahip olabilirsiniz ve bu durum siler veya reddeder ve size ne yaptığını söyleyen bir durum döndürür. Bu sadece "sil" diyen çok daha esnektir.


73

Böyle bir nesne asla yığın üzerinde oluşturulamaz. Her zaman öbek üzerinde. Ve silme işlemi bir arkadaş veya üye aracılığıyla yapılmalıdır. Bir ürün tek bir Nesne hiyerarşisi ve özel bir bellek yöneticisi kullanabilir; bu tür senaryolar özel bir dtor kullanabilir.

#include <iostream>
class a {
    ~a() {}
    friend void delete_a(a* p);
};


void delete_a(a* p)  {
    delete p;
}

int main()
{
    a *p = new a;
    delete_a(p);

    return 0;
}

19
Düzeltme: Bu tip bir nesne olabilir (ancak bir arkadaş veya kendisi kapsamına) yığın üzerinde oluşturulabilir.
Thomas Eding

Ayrıca, barındırılan bir uygulamada statik veya genel bir nesneyi ba (yani, "statik depolama süresi" olamaz) (yıkıcı program çıkışında çağırılacağı için).
Peter - Monica'yı yeniden


17

COM, örneği silmek için bu stratejiyi kullanır. COM, yıkıcıyı özel yapar ve örneği silmek için bir arabirim sağlar.

İşte bir Release yönteminin nasıl görüneceğine bir örnek.

int MyRefCountedObject::Release() 
{
 _refCount--;
 if ( 0 == _refCount ) 
 {
    delete this;
    return 0;
 }
 return _refCount;
}

ATL COM nesneleri bu kalıbın en iyi örneğidir.


8

Burada bulunan cevaplara ek olarak; özel yapımcılar ve yıkıcılar , yaratılan nesnelerin öbek üzerinde tahsis edilmesi gereken bir fabrika uygularken oldukça kullanışlıdır . Nesneler genel olarak statik bir üye veya arkadaş tarafından oluşturulur / silinir. Tipik bir kullanım örneği:

class myclass
{
public:
    static myclass* create(/* args */)  // Factory
    {
        return new myclass(/* args */);
    }

    static void destroy(myclass* ptr)
    {
        delete ptr;
    }
private:
    myclass(/* args */) { ... }         // Private CTOR and DTOR
    ~myclass() { ... }                  // 
}

int main ()
{
    myclass m;                          // error: ctor and dtor are private
    myclass* mp = new myclass (..);     // error: private ctor
    myclass* mp = myclass::create(..);  // OK
    delete mp;                          // error: private dtor
    myclass::destroy(mp);               // OK
}

7

Sınıf yalnızca kendiliğinden silinebilir. Referans sayılan bir nesne denemesi oluşturuyorsanız yararlıdır. Sonra nesneyi yalnızca bırakma yöntemi silebilir ve muhtemelen hatalardan kaçınmanıza yardımcı olur.


3

Özel yıkıcı hakkında soru sorduğunu biliyorum. Korumalı olanları nasıl kullanacağım. Ana fikir, ana sınıfı ekstra işlevsellik katan sınıfa işaretçi aracılığıyla silmek istemezsiniz.
Aşağıdaki örnekte GuiWindow'un bir HandlerHolder işaretçisi aracılığıyla silinmesini istemiyorum.

class Handler
{
public:
    virtual void onClose() = 0;
protected:
    virtual ~Handler();
};

class HandlerHolder
{
public:
    void setHandler( Handler* );
    Handler* getHandler() const;
protected:
    ~HandlerHolder(){}
private:
    Handler* handler_;
};

class GuiWindow : public HandlerHolder
{
public:
    void finish()
    {
        getHandler()->onClose();
    }

    virtual ~GuiWindow(){}
};

3

dirkgently yanlış. İşte yığın üzerinde oluşturulan özel c-tor ve d-tor ile nesne örneği (Burada statik üye işlevi kullanıyorum, ancak arkadaş işlevi veya arkadaş sınıfı ile de yapılabilir).

#include <iostream>

class PrivateCD
{
private:
    PrivateCD(int i) : _i(i) {};
    ~PrivateCD(){};
    int _i;
public:
    static void TryMe(int i)
    {
        PrivateCD p(i);
        cout << "inside PrivateCD::TryMe, p._i = " << p._i << endl;
    };
};

int main()
{
    PrivateCD::TryMe(8);
};

Bu kod çıktı üretir: PrivateCD içinde :: TryMe, p._i = 8


3
Dirkgently sınıfınızı kullanan kod yığını sınıfta örnek olamaz anlamına geliyordu eminim . Tabii ki yine de sınıf yöntemlerinde sınıfı sınıf yöntemleri içinde başlatabilirsiniz , çünkü bu bağlamda özel üyelere erişebilirsiniz.
Edward Loper

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.