Domanda

A che serve avere un distruttore come privato?

È stato utile?

Soluzione

Fondamentalmente, ogni volta che vuoi che un'altra classe sia responsabile del ciclo di vita degli oggetti della tua classe, o hai motivo di impedire la distruzione di un oggetto, puoi rendere privato il distruttore.

Ad esempio, se stai facendo una sorta di cosa di conteggio dei riferimenti, puoi avere l'oggetto (o il gestore che è stato "amico") responsabile del conteggio del numero di riferimenti a se stesso ed eliminarlo quando il numero colpisce zero. Un agente privato impedirebbe a chiunque altro di eliminarlo quando c'erano ancora riferimenti ad esso.

Per un'altra istanza, cosa succede se si dispone di un oggetto con un gestore (o se stesso) che potrebbe distruggerlo o rifiutare di distruggerlo a seconda di altre condizioni nel programma, come l'apertura di una connessione al database o il file scritto. Potresti avere un " request_delete " metodo nella classe o nel gestore che controllerà tale condizione e cancellerà o rifiuterà e restituirà uno stato che ti dice cosa ha fatto. È molto più flessibile che chiamare semplicemente " elimina " ;.

Altri suggerimenti

Un tale oggetto non può mai essere creato nello stack. Sempre sul mucchio. E la cancellazione deve essere effettuata tramite un amico o un membro. Un prodotto può utilizzare una singola gerarchia di oggetti e un gestore di memoria personalizzato - tali scenari possono utilizzare un dtor privato.

#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;
}

Quando non si desidera che gli utenti accedano al distruttore, ad esempio, si desidera che l'oggetto venga distrutto solo con altri mezzi.

http://blogs.msdn.com/larryosterman/ archive / 2005/07/01 / 434684.aspx fornisce un esempio, in cui l'oggetto viene contato come riferimento e dovrebbe essere distrutto dall'oggetto stesso quando il conteggio va a zero.

COM utilizza questa strategia per eliminare l'istanza. COM rende il distruttore privato e fornisce un'interfaccia per eliminare l'istanza.

Ecco un esempio di come sarebbe un metodo di rilascio.

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

Gli oggetti COM ATL sono un ottimo esempio di questo modello.

Aggiungendo alle risposte già presenti qui; costruttori e distruttori privati ??sono molto utili durante l'implementazione di una factory in cui è stata creata la fabbrica gli oggetti devono essere allocati sull'heap. Gli oggetti sarebbero, in generale, creati / cancellati da un membro statico o un amico. Esempio di un utilizzo tipico:

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
}

La classe può essere eliminata solo da sola. Utile se si sta creando qualche tentativo di oggetto contato di riferimento. Quindi solo il metodo di rilascio può eliminare l'oggetto, eventualmente aiutandoti a evitare errori.

So che stavi chiedendo del distruttore privato. Ecco come utilizzo quelli protetti. L'idea è che non si desidera eliminare la classe principale tramite il puntatore alla classe che aggiunge funzionalità extra alla principale.
Nell'esempio seguente non voglio che GuiWindow venga cancellato tramite un puntatore HandlerHolder.

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(){}
};

dirkgently è sbagliato. Ecco un esempio di oggetto con c-tor privato e d-tor creati in pila (sto usando la funzione membro statico qui, ma può essere fatto anche con la funzione amico o con la classe amico).

#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);
};

Questo codice produrrà output: all'interno di PrivateCD :: TryMe, p._i = 8

Potrebbe essere un modo per affrontare il problema in Windows in cui ciascun modulo può utilizzare un heap diverso, ad esempio Debug heap. Se il problema non viene gestito correttamente bad < a href = "https://stackoverflow.com/questions/443147/c-mix-new-delete-between-libs"> possono succedere cose .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top