Eu vejo muito código-fonte que usa o idioma PImpl em C ++. Suponho que seu objetivo seja ocultar os dados / tipo / implementação privados, para que ele possa remover a dependência e reduzir o tempo de compilação e o problema de inclusão de cabeçalho.
Mas as classes interface / puro-abstrato em C ++ também têm esse recurso, elas também podem ser usadas para ocultar dados / tipo / implementação. E para permitir que o chamador veja apenas a interface ao criar um objeto, podemos declarar um método de fábrica no cabeçalho da interface.
A comparação é:
Custo :
O custo da maneira da interface é menor, porque você nem precisa repetir a implementação da função de wrapper público
void Bar::doWork() { return m_impl->doWork(); }
, basta definir a assinatura na interface.Bem entendido :
A tecnologia de interface é melhor compreendida por todo desenvolvedor de C ++.
Desempenho :
O desempenho da interface não é pior que o idioma PImpl, um acesso extra à memória. Presumo que o desempenho seja o mesmo.
A seguir, está o pseudocódigo para ilustrar minha pergunta:
// Forward declaration can help you avoid include BarImpl header, and those included in BarImpl header.
class BarImpl;
class Bar
{
public:
// public functions
void doWork();
private:
// You don't need to compile Bar.cpp after changing the implementation in BarImpl.cpp
BarImpl* m_impl;
};
O mesmo objetivo pode ser implementado usando a interface:
// Bar.h
class IBar
{
public:
virtual ~IBar(){}
// public functions
virtual void doWork() = 0;
};
// to only expose the interface instead of class name to caller
IBar* createObject();
Então, qual é o objetivo do PImpl?
fonte
Impl
classe não quebrará oABI
, mas adicionar função pública na interface quebraráABI
.unordered_set
), sem Pimpl, eu preciso#include <unordered_set>
noMyClass.h
. Com Pimpl, só precisa incluí-lo no.cpp
arquivo, não o.h
arquivo e, portanto, tudo o resto que inclui isso ...Eu só quero abordar o seu ponto de desempenho. Se você usa uma interface, você necessariamente criou funções virtuais que NÃO serão incorporadas pelo otimizador do compilador. As funções PIMPL podem (e provavelmente serão, porque são muito curtas) ser incorporadas (talvez mais de uma vez se a função IMPL também for pequena). Uma chamada de função virtual não pode ser otimizada, a menos que você use otimizações completas de análise de programa que levam muito tempo para serem realizadas.
Se sua classe PIMPL não for usada de maneira crítica ao desempenho, esse ponto não importará muito, mas sua suposição de que o desempenho é o mesmo vale apenas em algumas situações, não em todas.
fonte
Esta página responde à sua pergunta. Muitas pessoas concordam com sua afirmação. O uso do Pimpl tem as seguintes vantagens sobre os campos / membros privados.
O idioma Pimpl é uma otimização em tempo de compilação, uma técnica de quebra de dependência. Reduz arquivos de cabeçalho grandes. Reduz o cabeçalho apenas para a interface pública. O comprimento do cabeçalho é importante no C ++ quando você pensa em como ele funciona. #include concatena efetivamente o arquivo de cabeçalho com o arquivo de origem - lembre-se de que as unidades C ++ pré-processadas podem ser muito grandes. O uso do Pimpl pode melhorar o tempo de compilação.
Existem outras técnicas melhores de quebra de dependência - que envolvem a melhoria do seu design. O que os métodos privados representam? Qual é a responsabilidade única? Eles deveriam ser outra classe?
fonte