2010-01-26 14 views
6

Recentemente ho scritto un codice simile a questo:classe astratta - nasconde implementazione in C++ pratica

messagehandler.h:

#include "message.h" 
class MessageHandler { 
public: 
    virtual ~MessageHandler() {} 
    virtual void HandleMessage(Message *msg) = 0: 
}; 

persistmessagehandler.h:

MessageHandler *CreatePersistMessageHandler(); 

persistmessagehandler. cpp:

#include "messagehandler.h" 
#include "persist.h" 

class PersistMessageHandler : public MessageHandler { 
private: 
    PersistHandle ph; 
    size_t count; 
    InternalCheck(); 
public: 
    PersistMessageHandler(int someParam); 
    virtual ~PersistMessageHandler(); 
    virtual void HandleMessage(Message *msg): 
}; 
PersistMessageHandler::PersistMessageHandler(int someParam) 
{ 
    ph.Initialize(); 
} 
... rest of implementation. 

MessageHandler *CreatePersistMessageHandler(int someParam) 
{ 
    return new PersistMessageHandler(someParam); 
} 

Il ragionamento qui è quello di nascondere PersistMessageHandler. I client non devono includere un'intestazione per la classe PersistMessageHandler, con tutti gli include e tipi che potrebbero richiedere l'implementazione e separare in modo più pulito l'interfaccia e l'implementazione. . Sarà sempre assegnato dinamicamente comunque,

Tutti gli utenti di PersistMessageHandler chiameranno semplicemente CreatePersistMessageHandler (..); ottenere direttamente o indirettamente uno da una fabbrica.

Ma. Non ho visto questo approccio usato molto altrove. È la buona pratica di cui sopra? Ci sono altre/migliori alternative per casi semplici?

+0

Perché qualcuno dovrebbe mai abbreviare "Messaggio" in "Messge"? È un errore di battitura? – unwind

+0

Ottima domanda! Lo faccio sempre e mi sono sempre chiesto se fosse kosher.Tranne la mia dichiarazione è: 'std :: auto_ptr CreatePersistMessageHandler();' –

+0

Vedere anche http://stackoverflow.com/questions/825018/pimpl-idiom-vs-pure-virtual-class-interface – Frank

risposta

6

Devi sempre nasconderti il ​​più possibile. Il tuo modo (mettere le classi di implementazione in .cpp) è un modo comune per farlo in C++.

1

Sicuro: assomiglia allo a form of the factory pattern. Gli utenti della fabbrica non sono interessati ai suoi dettagli interni, si preoccupano solo delle cose che crea.

2

Questo è un buon modo per nascondere i dettagli di implementazione dai client. Se stai lavorando in Windows, potresti anche considerare l'utilizzo di un'interfaccia __ invece di una classe base astratta.

Un'interfaccia è un'estensione del compilatore MSVC che ha l'aspetto di una classe base astratta, ma ha regole diverse per la creazione e la distruzione rispetto a una normale classe C++. È il modo standard di lavorare in Windows, quindi ci sono delle funzionalità supportate dal sistema per lavorare con oggetti out-of-process e per usarli nel codice .NET.

0

Ridurre al minimo la dipendenza sui dettagli di implementazione è davvero grande, e nascondere le cose al di là di classe astratta di base (ABC, alias interfaccia) è un buona e soluzione idiomatica.

L'aspetto negativo dell'utilizzo di ABC è che si perde la semantica del valore della classe che potrebbe essere o non essere accettabile/desiderabile.

Una tecnica che nasconde anche i dettagli di implementazione senza questo inconveniente è Pimpl. Indovina dovresti essere consapevole.

Preferisco l'ABC nella maggior parte dei casi.

+0

@CraigMcQueen typo , dovrebbe essere ABC (classe base astratta). Grazie! –

Problemi correlati