Quindi, mi chiedo che questa tecnica sia davvero utilizzata nella pratica? Dovrei usarlo ovunque o con cautela?
Certo che è usato. Lo uso nel mio progetto, in quasi tutte le classi.
Motivi per l'utilizzo del linguaggio PIMPL:
Compatibilità binaria
Quando stai sviluppando una libreria, puoi aggiungere / modificare campi XImpl
senza interrompere la compatibilità binaria con il tuo client (il che significherebbe arresti anomali!). Poiché il layout binario della X
classe non cambia quando si aggiungono nuovi campi alla Ximpl
classe, è sicuro aggiungere nuove funzionalità alla libreria negli aggiornamenti delle versioni minori.
Ovviamente, puoi anche aggiungere nuovi metodi non virtuali pubblici / privati a X
/ XImpl
senza interrompere la compatibilità binaria, ma è alla pari con la tecnica standard di intestazione / implementazione.
Dati nascosti
Se stai sviluppando una libreria, specialmente una proprietaria, potrebbe essere desiderabile non rivelare quali altre librerie / tecniche di implementazione sono state utilizzate per implementare l'interfaccia pubblica della tua libreria. O a causa di problemi di proprietà intellettuale o perché ritieni che gli utenti potrebbero essere tentati di fare ipotesi pericolose sull'implementazione o semplicemente rompere l'incapsulamento usando terribili trucchi di lancio. PIMPL risolve / mitiga questo.
Tempo di compilazione
Il tempo di compilazione è ridotto, poiché è X
necessario ricostruire solo il file di origine (implementazione) quando si aggiungono / rimuovono campi e / o metodi alla XImpl
classe (che associa all'aggiunta di campi / metodi privati nella tecnica standard). In pratica, è un'operazione comune.
Con la tecnica standard di intestazione / implementazione (senza PIMPL), quando si aggiunge un nuovo campo a X
, tutti i client che allocano X
(sia in stack che in heap) devono essere ricompilati, perché devono regolare le dimensioni dell'allocazione. Bene, ogni cliente che non mai allocare X anche bisogno di essere ricompilato, ma è solo in testa (il codice risultante sul lato client sarà lo stesso).
Inoltre, con la separazione standard di intestazione / implementazione XClient1.cpp
deve essere ricompilata anche quando è X::foo()
stato aggiunto X
e X.h
modificato un metodo privato , anche se XClient1.cpp
non è possibile chiamarlo per motivi di incapsulamento! Come sopra, è puro sovraccarico ed è correlato a come funzionano i sistemi di build C ++ nella vita reale.
Naturalmente, la ricompilazione non è necessaria quando si modifica semplicemente l'implementazione dei metodi (perché non si tocca l'intestazione), ma è alla pari con l'intestazione / tecnica di implementazione standard.
Si consiglia di utilizzare questa tecnica nei sistemi embedded (dove le prestazioni sono molto importanti)?
Dipende da quanto è potente il tuo obiettivo. Tuttavia l'unica risposta a questa domanda è: misurare e valutare ciò che si guadagna e si perde. Inoltre, tieni presente che se non stai pubblicando una libreria destinata ai client per essere utilizzata nei sistemi incorporati, si applica solo il vantaggio del tempo di compilazione!
struct XImpl : public X
. Mi sembra più naturale. C'è qualche altro problema che mi sono perso?