Pregunta

Fondo

Tengo una clase abstracta, algo así como

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

Habrá muchas clases concretas que simplemente implementan Hacer conversión 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
     }
};

Habrá muchas implementaciones concretas como esta.He creado un archivo de encabezado que dice: CharacterConverter.h que tiene la clase abstracta IConvertidor.

Pregunta

Dado que mis clases concretas simplemente implementan el Hacer conversión método, ¿es necesario crear archivos de encabezado separados para cada clase concreta?Quiero decir, ¿es necesario crear? ImageConverter.h, TextConverter.h y así sucesivamente para todas las clases concretas?Todos estos archivos de encabezado contendrán el mismo código como IConvertidor clase abstracta.

¿Alguna idea?

¿Fue útil?

Solución

Algo que podría considerar, dependiendo del resto de su diseño, es una fábrica, donde su clase abstracta tiene un método estático (o varios métodos estáticos, dependiendo de cómo ponerlo en práctica) que construye la subclase apropiada y lo devuelve como un iconverter *. Con esto, se puede exponer sólo la definición abstracta en el archivo de cabecera, y tienen todas las definiciones de clases concretas e implementaciones en un solo archivo .cpp junto con la implementación de superclase. Esto se hace un poco difícil de manejar si sus subclase son grandes, pero con clases más pequeñas se reduce el número de archivos que tiene que manejar.

Pero, como otros han señalado, que es en última instancia una cuestión de criterio. Los únicos problemas de rendimiento estarían relacionados con la compilación; más archivos cpp podrían tomar (ligeramente) más tiempo para compilar y más archivos de cabecera podrían aumentar análisis de la dependencia. Pero no hay necesidad de que todos los archivos de cabecera tiene un coste por juego y viceversa.

A partir de los comentarios, me gustaría recomendar una estructura como esta:

IConverter.h ==> definición de Iconverter
Converters.h ==> Definiciones de todas las subclases
IConverter.cpp ==> incluye IConverter.h y Converters.h, contiene ejecución de Iconverter funcionalidad abstracta (método de fábrica estática y cualquier funcionalidad heredable)
TextConvter.cpp, ImagerConverter.cpp, etc. ==> cpp separados para cada subclase, cada una conteniendo IConverter.h y Converters.h

Esto le permite sólo para incluir el IConverter.h en cualquier cliente que utilizan la fábrica y funcionalidad genérica. Poner todas las otras definiciones en una sola cabecera le permite consolidar si son básicamente los mismos. cpp separadas le permiten tomar ventaja de los beneficios mencionados por Brian compilador. Se podría inline las definiciones de las subclases en los archivos de cabecera como se ha mencionado, pero que en realidad no comprar nada. Su compilador suele ser más inteligente que tú cuando se trata de optimizaciones como en línea.

Otros consejos

No se requiere. Se trata básicamente de una cuestión de criterio.

Si la aplicación es simple para cada clase se puede poner a todos en un .h y uno .cpp

Si las implementaciones son un poco más, entonces es probablemente más limpia de usar un archivo .cpp y .h separado para cada uno.

Algunas ventajas de utilizar un .h diferente / .cpp para cada clase:

  • Se mantendrá el código organizado y limpio
  • Reducción del trabajo de compilación: Un cambio en una de las implementaciones no tendrá que volver a compilar todos los demás
  • Menor tiempo de compilación: Varios compiladores pueden compilar varios archivos a la vez, como interruptor de Visual Studio / MP. Con varios archivos tendrá un tiempo de compilación más rápido.
  • Otros archivos pueden incluir sólo lo que necesitan en lugar de todo
  • más rápido tiempo de enlace: enlaces de tiempo se reducirá debido a la vinculación incremental
  • Uso de control de versiones se puede mirar hacia atrás sólo los cambios en una clase derivada particular, en lugar de tener que ir a través de todos los cambios realizados en el archivo .h masiva 1 / .cpp para encontrar que un cambio en una clase derivada en particular.

Probablemente obtendrá respuestas en ambos sentidos.

Yo diría que, para cualquier convertidores triviales, teniendo todos ellos en un solo par .h / Cpp es suficiente y que es una exageración para dividir cada uno en un solo par. Creo que la solución de compromiso de mantenimiento de un montón de archivos en comparación con el mantenimiento de un montón de métodos dentro de un solo archivo vale la pena en este caso.

conversiones complejas probablemente merecen sus propios pares de archivos.

Necesitará las definiciones de las clases concretas para crear objetos, por lo que tendrá que poner las definiciones en un archivo .h en alguna parte. ¿Qué archivo se los pone en depende de usted.

La mejor respuesta a esto es lo más fácil de leer. En un extenso archivo fuente va a ser difícil para usted y otros programadores a seguir. Por otro lado, muchos pequeños archivos de origen (la mitad de pantalla completa) es igual de malo.

Uno de los puntos principales de la creación de una clase de interfaz es para que los clientes pueden ser depende de la interfaz abstracta en lugar de la aplicación concreta, y que son libres para cambiar la implementación sin afectar a los clientes.

Poner las declaraciones concretas en los mismos ficheros de cabecera como las declaraciones de interfaz derrota a esto, por lo que ahora si cambia un detalle de implementación de una clase concreta, sus clientes tendrían que volver a compilar.

probablemente sería mejor usar las fábricas o los punteros de función.

Sin embargo, de una manera particularmente desagradable que viene a la mente es el uso de una macro para declarar sus clases concretas. Por ejemplo:

En la parte inferior de IConverter.h incluir la siguiente macro

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

A continuación, en MyConverter1.cpp

DECLARE_CONVERTER_CLASS(MyConverter1)

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

Yuck: -)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top