Então, eu estou querendo saber se esta técnica é realmente usada na prática? Devo usá-lo em qualquer lugar ou com cautela?
Claro que é usado. Eu o uso no meu projeto, em quase todas as aulas.
Razões para usar o idioma PIMPL:
Compatibilidade binária
Ao desenvolver uma biblioteca, você pode adicionar / modificar campos XImpl
sem interromper a compatibilidade binária com seu cliente (o que significaria falhas!). Como o layout binário da X
classe não muda quando você adiciona novos campos à Ximpl
classe, é seguro adicionar novas funcionalidades à biblioteca em atualizações de versões secundárias.
Obviamente, você também pode adicionar novos métodos não virtuais públicos / privados a X
/ XImpl
sem interromper a compatibilidade binária, mas isso é semelhante à técnica de cabeçalho / implementação padrão.
Ocultar dados
Se você estiver desenvolvendo uma biblioteca, especialmente uma proprietária, pode ser desejável não divulgar quais outras bibliotecas / técnicas de implementação foram usadas para implementar a interface pública da sua biblioteca. Por causa de problemas de propriedade intelectual ou porque você acredita que os usuários podem ficar tentados a assumir suposições perigosas sobre a implementação ou apenas quebrar o encapsulamento usando terríveis truques de elenco. O PIMPL resolve / mitiga isso.
Tempo de compilação
O tempo de compilação diminui, pois somente o arquivo de origem (implementação) X
precisa ser reconstruído quando você adiciona / remove campos e / ou métodos à XImpl
classe (que mapeia a adição de campos / métodos particulares na técnica padrão). Na prática, é uma operação comum.
Com a técnica de cabeçalho / implementação padrão (sem PIMPL), quando você adiciona um novo campo a X
, todo cliente que aloca X
(na pilha ou na pilha) precisa ser recompilado, porque deve ajustar o tamanho da alocação. Bem, todo cliente que nunca aloca o X também precisa ser recompilado, mas é apenas um overhead (o código resultante no lado do cliente será o mesmo).
Além do mais, com a separação de cabeçalho / implementação padrão XClient1.cpp
precisa ser recompilada mesmo quando um método privado X::foo()
foi adicionado X
e X.h
alterado, mesmo que XClient1.cpp
não seja possível chamá-lo por motivos de encapsulamento! Como acima, é pura sobrecarga e está relacionada à forma como os sistemas de construção C ++ da vida real funcionam.
Obviamente, a recompilação não é necessária quando você apenas modifica a implementação dos métodos (porque você não toca no cabeçalho), mas isso é semelhante à técnica padrão de cabeçalho / implementação.
Essa técnica é recomendada para uso em sistemas embarcados (onde o desempenho é muito importante)?
Isso depende de quão poderoso é o seu alvo. No entanto, a única resposta para essa pergunta é: meça e avalie o que você ganha e perde. Além disso, leve em consideração que, se você não estiver publicando uma biblioteca para ser usada em sistemas embarcados por seus clientes, apenas a vantagem do tempo de compilação se aplica!
struct XImpl : public X
. Isso parece mais natural para mim. Há algum outro problema que eu perdi?