TN017: Distruggere oggetti Window

Questa nota viene descritto l'utilizzo della funzione membro CWnd::PostNcDestroy . Utilizzare questa funzione se si desidera effettuare personalizzate allocazione di CWnd-derivati oggetti.

Questa nota spiega anche alcune delle ragioni per la regola cardinale:

Per eliminare un oggetto Windows C++, utilizzare DestroyWindow non "Elimina".

Questo è importante. Se si seguono le linee guida qui sotto, avete qualche problema di pulizia (ad esempio, dimenticando di cancellare/liberare memoria C++, dimenticando di liberare risorse di sistema come HWNDs o liberare gli oggetti troppe volte).

Il problema

Windows oggetti (oggetti di classi derivate da CWnd) rappresentano un oggetto C++ (allocato nell'heap dell'applicazione) sia un HWND (allocati in risorse di sistema dal window manager). Poiché ci sono diversi modi per distruggere un oggetto window, dobbiamo fornire un insieme di regole che impediscono la risorsa di sistema o le perdite di memoria dell'applicazione e che impediscono gli oggetti e maniglie Windows dall'essere distrutto più di una volta.

Questo è più di un problema di gestione della memoria. La presenza di una finestra di Windows ha impatto di interfaccia utente: una finestra disegnata sullo schermo; una volta che è distrutto c'è anche un impatto sulle risorse di sistema. Perdite di memoria C++ nello spazio indirizzo di applicazione non è così male come perdite di risorse di sistema.

Distruggendo Windows

Sono i due modi consentiti per distruggere un oggetto Windows:

Il primo caso è di gran lunga il più comune. Questo caso si applica anche se DestroyWindow non viene chiamato direttamente dal codice. Il è il caso, quando l'utente chiude direttamente una finestra cornice (comportamento predefinito WM_CLOSE è per chiamare DestroyWindow), e quando una finestra padre viene distrutto, Windows chiama DestroyWindow per tutti i bambini.

Il secondo caso, l'uso dell'operatore delete su oggetti di Windows, dovrebbe essere molto raro e solo nei casi sotto riportate.

Pulitura automatica con CWnd::PostNcDestroy

Quando la distruzione di una finestra di Windows, l'ultimo messaggio Windows inviato alla finestra è WM_NCDESTROY. CWnd gestore predefinito per quel messaggio (CWnd::OnNcDestroy) staccherà l' HWND dal oggetto C++ e chiamare che la funzione virtuale PostNcDestroy. Alcune classi di eseguire l'override di questa funzione per eliminare l'oggetto C++.

L'implementazione predefinita di CWnd::PostNcDestroy non fa nulla che è appropriato per oggetti window allocato su stack frame o incorporati in altri oggetti. Non è appropriato per gli oggetti della finestra che sono progettati per essere allocato da loro stessi sull'heap (non incorporato in altro oggetto C++).

Quelle classi che sono progettati per essere allocata da soli nell'heap di eseguire l'override della funzione membro PostNcDestroy per eseguire un "eliminare questo". Questa affermazione ti libererà qualsiasi memoria C++ associato all'oggetto C++. Anche se il distruttore di CWnd predefinito chiama DestroyWindow se m_hWnd è diverso da NULL, questo non porta alla ricorsione infinita poiché l'handle sarà disinvolta e NULL durante la fase di pulitura.

&Notanbsp;CWnd::PostNcDestroy viene normalmente chiamato dopo le finestre WM_NCDESTROY messaggio viene elaborato, come parte della distruzione della finestra, e l' HWND e l'oggetto window C++ non più sono attaccati. CWnd::PostNcDestroy anche essere chiamato nell'implementazione della maggior parte delle chiamate Crea se si verifica l'errore (vedi sotto per le regole di pulitura automatica).

Classi di pulizia automatica

Le seguenti classi non sono progettate per la pulizia automatica. Essi sono normalmente incorporati in altri oggetti C++ o sullo stack:

Le seguenti classi sono progettate per auto-pulitura. Essi sono normalmente allocate da soli nell'heap:

Se si desidera rompere qualsiasi di queste regole, è necessario eseguire l'override della funzione membro PostNcDestroy nella classe derivata. Per aggiungere la classe auto-pulitura, semplicemente chiamare la classe base e poi fare un eliminare questo. Per rimuovere la pulitura automatica dalla vostra classe, chiamare CWnd::PostNcDestroy direttamente anziché il membro PostNcDestroy nella vostra classe base diretta.

L'uso più comune di quanto sopra è quello di creare una finestra di dialogo non modale che può essere allocata nell'heap.

Quando a chiamata 'Elimina'

Per eliminare un oggetto Windows si consiglia di chiamare DestroyWindow, sia la funzione membro C++ o globale :: DestroyWindow API.

Non chiamare il global :: DestroyWindow API per distruggere una finestra figlio MDI, invece utilizzare la funzione membro virtual CWnd:: DestroyWindow.

Per gli oggetti C++ finestra che non effettuano auto-pulitura, utilizzando DestroyWindow invece di eliminare evita problemi di dover chiamare DestroyWindow CWnd:: ~ CWnd distruttore dove VTBL non sta puntando alla classe derivata correttamente. Questo può portare a sottili bug così la versione di diagnostica (debug) di MFC ti avviserà con

Attenzione: la chiamata DestroyWindow CWnd:: ~ CWnd
 nbsp; OnDestroy o Post&NcDestroy in classe derivata non saranno chiamati

Nel caso di oggetti di Windows C++ che eseguire auto-pulizia, è necessario chiamare DestroyWindow. Se si utilizza operatore eliminare direttamente, l'allocatore di memoria diagnostico MFC ti avviserà che la liberazione di memoria due volte (la prima chiamata a eliminare ) così come le chiamate indirette a "eliminare questo" nell'attuazione auto-pulitura di PostNcDestroy.

Dopo la chiamata DestroyWindow su un oggetto auto-pulitura, l'oggetto C++ sarà ancora in giro, ma m_hWnd sarà NULL. Dopo la chiamata DestroyWindow su un oggetto auto-pulitura, l'oggetto C++ sarà andato, liberato dall'operatore delete C++ nell'attuazione del PostNcDestroy auto-pulitura..

&Note tecniche per numero |nbsp; Note tecniche per la categoria

Index