2009-10-29 20 views
6

Algunas clases, como excepciones o plantillas, solo necesitan el archivo de encabezado (.h), a menudo no hay un .cpp relacionado con ellas.¿Es una buena práctica crear siempre un .cpp para cada .h en un proyecto de C++?

He visto algunos proyectos (para algunas clases) no hay archivos .cpp asociados a los archivos de encabezados, tal vez porque la implementación es tan corta que se hace directamente en .h, o tal vez para otra razones, como clases de plantilla, donde es obligatorio incluir la implementación en el encabezado.

¿Cuál es su opinión, si una clase es demasiado corta, podría evitar crear un archivo .cpp y escribir el código directamente en el archivo de encabezado? Si el código está escrito en el archivo de encabezado, ¿debería incluir un .cpp vacío para que los archivos en el proyecto permanezcan consistentes?

Respuesta

14

No agregaría archivos innecesarios .cpp. Cada archivo .cpp que agregue debe compilarse, lo que solo ralentiza el proceso de compilación.

En general, el uso de su clase solo requerirá el archivo de encabezado de todos modos - No veo ninguna ventaja para un archivo .cpp "vacío" para la consistencia en el proyecto.

+1

Realmente no estoy de acuerdo, el código escrito dentro de un encabezado debe compilarse tantas veces como esté incluido, mientras que debe compilarse solo una vez si está dentro de un archivo fuente (.c). Sin embargo, estoy de acuerdo en que es bastante conveniente y el tiempo de compilación no es un problema importante para mí. – Ben

+0

@Ben, la suposición sería que cualquier código que se compilaría en el archivo h sería un código de tamaño en línea (o al menos un código que podría agregarse a un encabezado precompilado). Por lo tanto, el tiempo de compilación para el archivo h no sería un problema. – kidnamedlox

+1

@kidnamedlox: Exactamente. @Ben: si incluye código de cualquier tamaño que no sea el que debe contener, acepto que un archivo .cpp es una buena idea. Solo cuando el código es muy pequeño, creo que poner un archivo .cpp vacío solo por un archivo .cpp no ​​es una buena práctica. –

8

No. Si no hay nada que necesite estar en .cpp, no necesita uno.

+0

A menos que tenga una dependencia cíclica en algún lugar de su diseño por diseño, no por accidente. – Chad

+0

No estoy seguro de lo que quiere decir ... por favor explique. – Grumdrig

+0

Si tiene una dependencia cíclica que desea resolver de esta manera, entonces tiene algo que debe estar en .cpp, por lo que la respuesta de Grumdrig aún se cumple. – jalf

1

Regla de oro, mantenga la clase relacionada junta en el mismo archivo. Las clases más importantes deben colocarse en sus propios archivos .hpp y .cpp. La razón de esto es que en proyectos grandes tienes hasta 10.000 clases y anteponer esa cantidad de archivos al usuario e IDE normalmente hacen que las cosas se rompan.

1

Hay bibliotecas muy útiles y exitosas, como muchas en boost, que son solo de encabezado.

1

Si algunas clases son cortas y parecen estar alineadas, tiendo a ponerlas todas juntas en types.h - el único encabezado que no considero que merezca un archivo .cpp.

Sin embargo, la mayoría de las clases superan tanto la posibilidad de entrar solo en el encabezado como la posibilidad de entrar en types.h.

Algunos ejemplos de lo que hago. Considero la clase para la implementación del vector tridimensional Vector3 para merecer su .h y .cpp, a pesar de ser simple. Pero Position realmente no se lo merece; después de todo, incluso sería una P.O.D. estructura, si no fuera por ese molesto getDistance() que me gusta implementar allí.

Así que no, no todas las clases merecen sus archivos .cpp y .h. Pero la mayoría lo hace, y aquellos que definitivamente no llegan a pararse en un encabezado solitario. Si son tan cortos como para caber solo en el encabezado, o bien se acurrucan junto con otras clases cortas, o van al encabezado de la clase con la que están estrechamente relacionados.

1

Mi regla de oro es que cualquier método que necesite más de una línea de código para expresar va a un archivo .cpp.

Para obtener más información sobre este tema, es posible que desee consultar esta vieja pregunta mía: C++ code in header files. No creo que tu pregunta sea un duplicado exacto, pero está lo suficientemente cerca como para que la leas.

1

Consulte también this question - los archivos de encabezado solo deben ser para declaraciones.

Si tiene código compilable incluido en varios lugares (de su comentario: "¿debo evitar crear un archivo .cpp y escribir el código directamente en el archivo de encabezado?"), se compilará cada vez (aunque es posible que tenga encabezados precompilados) y el enlazador resolverá (o no) el código de objeto inflado.

El hecho de que la definición de clase sea pequeña no significa que deba ser en el archivo de cabecera a menos que la definición es también igual que la declaración - por ejemplo, una clase virtual pura o un tipo simple como se menciona en la otra respuesta

+0

Desafortunadamente, no todos los compiladores admiten la creación de enlaces en tiempo de enlace, e incluso aquellos que tienen mejor soporte de alineación en tiempo de compilación que en tiempo de enlace. Por lo tanto, debe colocar pequeñas funciones críticas que desee incluir en encabezados o hacer contorsiones en tiempo de compilación, como Unity Builds. – Adisak

+0

Una definición de clase ** debe ** estar en un encabezado, si tiene la intención de utilizar la clase en varias Unidades de traducción. Tal vez estabas pensando en las definiciones de la clase _methods_? Esos pueden estar seguros en el .cpp. La razón es porque el vinculador puede resolver funciones y métodos en tiempo de enlace, pero no clases enteras. – MSalters

+0

@MSalters: Quiere decir que una declaración ** de clase debe estar en un encabezado. – quamrana

3

su realmente caballos para los cursos:.

  • sólo encabezado clases : por ejemplo, plantilla clases
  • Encabezado y cpp : separa la declaración de la implementación.
  • cpp solamente: su main() puede vivir en uno de estos.

El código fuente del archivo de cabecera es a veces la única forma de escribir plantillas reutilizables. Consulte boost para obtener muchos ejemplos de esto.

Encabezado y cpp es más 'normal'. Separa la declaración de la implementación y puede acelerar la compilación cuando el compilador no tiene que leer implementaciones muchas veces. Es posible que desee comenzar aquí y luego ver cómo funciona la implementación y si el archivo cpp se vacía, puede eliminarlo.
Otro punto aquí es que tendrá su #include "foo.h" en la parte superior de foo.cpp para demostrar que cualquier otra persona puede hacer esto y no tener errores de compilación.

Cpp solo archivos. main() puede vivir aquí, y he puesto clases de prueba cppUnit en archivos como este.

1

Hay una ventaja para crear siempre un .cpp para cada .h, incluso cuando el primero estaría vacío: se aplica en tiempo de compilación que los archivos de encabezado son independientes. Esto se relaciona con el guideline de incluir por primera vez en foo.h foo.cpp:

Con el orden preferido, si directorio2/foo2.h omite cualquier necesaria incluye, la acumulación de dir/foo.cpp se romperá. Por lo tanto, esta regla asegura que los rompimientos de compilación aparecen primero para las personas que trabajan en estos archivos, no para las personas inocentes en otros paquetes.

Cuestiones relacionadas