Pergunta

Fundo

Eu tenho uma classe abstrata, algo como

class IConverter{
    public:
    virtual void DoConvertion() = 0;
};

Haverá muitas classes concretas que apenas implementa DoConvertion método.

class TextConverter : public IConverter{
    public:
    virtual void DoConvertion(){
         // my code goes here
     }
};

class ImageConverter : public IConverter{
    public:
    virtual void DoConvertion(){
         // my code goes here
     }
};

Haverá implementação muitos concreta como esta. Eu criei um exemplo arquivo de cabeçalho, CharacterConverter.h , que tem a classe abstrata iConverter .

Pergunta

Uma vez que minhas aulas de concreto apenas implementar o DoConvertion método, não é necessário para criar arquivos de cabeçalho separados para cada classe concreta? Eu quero dizer é que necessário para criar ImageConverter.h , TextConverter.h e assim por diante para todas as classes de concreto? Todos esses arquivos de cabeçalho vai conter o mesmo código como iConverter classe abstrata.

Qualquer pensamento?

Foi útil?

Solução

Algo que você pode considerar, dependendo do resto do seu design, é uma fábrica, onde sua classe abstrata tem um método estático (ou vários métodos estáticos, dependendo de como você implementá-lo) que constrói a subclasse e retorna como apropriado um iConverter *. Com isso, você pode expor apenas a definição abstrata no cabeçalho do arquivo, e tem todas as definições de classe de concreto e implementações em um único arquivo .cpp, juntamente com a implementação de super classe. Isto torna-se um pesado pouco se seus subclasse são grandes, mas com classes menores que reduz o número de arquivos que você tem que gerenciar.

Mas, como outros apontaram, é em última análise, uma chamada de julgamento. Os únicos problemas de desempenho estaria relacionada a compilação; mais arquivos CPP pode levar (ligeiramente) mais tempo para compilar e mais arquivos de cabeçalho pode aumentar a análise de dependência. Mas não há nenhuma exigência de que cada arquivo de cabeçalho têm um CPP correspondente e vice-versa.

Com base nos comentários, eu recomendo uma estrutura como esta:

IConverter.h ==> definição de iConverter
Converters.h ==> definições de todas as subclasses
IConverter.cpp ==> incluem IConverter.h e Converters.h, contêm implementação da funcionalidade abstrato iConverter (método de fábrica estático e qualquer funcionalidade hereditária)
TextConvter.cpp, ImagerConverter.cpp, etc. ==> cpp separadas para cada subclasse, cada um contendo IConverter.h e Converters.h

Isso permite que você inclua somente o IConverter.h em todos os clientes que utilizam a fábrica e funcionalidade genérica. Colocar todas as outras definições em um único cabeçalho permite consolidar, se todos eles são basicamente o mesmo. cpp separados permitem-lhe tirar partido dos benefícios do compilador mencionados por Brian. Você poderia inline definições das subclasses em arquivos de cabeçalho como mencionado, mas que realmente não comprar nada. Seu compilador geralmente é mais esperto do que você é quando se trata de otimizações como em linha.

Outras dicas

Não é necessário. É basicamente um julgamento.

Se a aplicação é simples para cada classe que você pode colocá-los todos em um .h e um .cpp

Se as implementações são um pouco mais, então provavelmente é mais limpo para usar um arquivo e.cpp separado para cada um.

Algumas vantagens de usar um diferente .h / .cpp para cada classe:

  • Vai manter o código organizado e limpo
  • Redução do trabalho de compilação: Uma mudança em uma das implementações não precisará recompilar todos os outros
  • tempo mais rápido compilando: Vários compiladores pode compilar vários arquivos de uma só vez, como opção / MP do Visual Studio. Com vários arquivos que você terá um tempo mais rápido de compilação.
  • Outros arquivos pode incluir apenas o que eles precisam, em vez de tudo
  • Mais rápido tempo de ligação: Ligando o tempo será reduzido devido à vinculação incremental
  • Usando controle de versão você pode olhar para trás apenas as alterações em uma classe derivada particular, em vez de ter que passar por todas as alterações feitas no arquivo 1 .h / .cpp enorme para achar que uma mudança em uma classe derivada particular.

Você provavelmente vai obter respostas para os dois lados.

Eu diria que, por qualquer conversores triviais, tendo todos eles em um único par .h / CPP é suficiente e que é um exagero para dividir cada um em um único par. Eu acho que a troca de manutenção de lotes de arquivos vs. manutenção de um monte de métodos dentro de um único arquivo é pena neste caso.

conversões complexas provavelmente merecem seus próprios pares de arquivo.

Você vai precisar de definições das classes concretas para criar objetos, então você precisa colocar essas definições em um algum lugar ficheiro.h. Qual arquivo você colocá-los em é com você.

A melhor resposta para isso é que é mais fácil de ler. Um arquivo longo fonte vai ser difícil para você e outros programadores a seguir. Por outro lado, muitos pequenos arquivos de origem (meia tela-cheia) é tão ruim.

Um dos principais pontos de criação de uma classe de interface é para que os clientes podem ser depender da interface abstrata ao invés da implementação concreta, e então você está livre para mudar a implementação sem afetar os clientes.

Pondo as declarações concretas nos mesmos arquivos de cabeçalho como as declarações de interface derrotas isso, agora se você alterar um detalhe de implementação de uma classe concreta, seus clientes seria necessário re-compilação.

Você provavelmente estaria melhor fora de usar fábricas ou ponteiros de função.

No entanto, de um modo particularmente desagradável que vem à mente é usando uma macro para declarar suas classes concretas. Por exemplo:

Na parte inferior da IConverter.h incluem o seguinte macro

#define DECLARE_CONVERTER_CLASS(CLASS_NAME) \
class CLASS_NAME : public IConverter\
{ \
    public: \
    CLASS_NAME() {} \
    virtual void DoConversion(); \
}; \

Então, em MyConverter1.cpp

DECLARE_CONVERTER_CLASS(MyConverter1)

virtual void MyConverter1::DoConversion()
{
    ...
}

Yuck: -)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top