Organización de archivos de encabezado de clase C++


¿Cuáles son las pautas de codificación y organización de archivos de C++ que sugiere para las personas que tienen que lidiar con muchas clases interdependientes distribuidas en varios archivos de código fuente y encabezado?

Tengo esta situación en mi proyecto y resolver errores relacionados con la definición de clase cruzando varios archivos de encabezado se ha convertido en un gran dolor de cabeza.

Author: Don Kirkby, 2008-12-06

6 answers

Algunas pautas generales:

  • Empareja tus interfaces con implementaciones. Si tiene foo.cxx, es mejor que todo lo definido allí se declare en foo.h.
  • Asegúrese de que cada archivo de cabecera #incluya todas las demás cabeceras o declaraciones forward necesarias para la compilación independiente.
  • Resiste la tentación de crear un encabezado "todo". Siempre son problemas en el camino.
  • Poner un conjunto de funciones relacionadas (e interdependientes) en una sola fila. Java y otros entornos fomentan una clase por archivo. Con C++, a menudo desea un conjunto de clases por archivo. Depende de la estructura de tu código.
  • Siempre que sea posible, prefiera la declaración directa sobre #include s. Esto le permite romper las dependencias de encabezado cíclico. Esencialmente, para dependencias cíclicas entre archivos separados, desea un gráfico de dependencias de archivos que se vea algo como esto:
    • A.cxx requiere A.h y B.h
    • B.cxx requiere A.h y B.h
    • A.h requiere B.h
    • B.h es independiente (y forward-declara clases definidas en A.h)

Si su código está destinado a ser una biblioteca consumida por otros desarrolladores, hay algunos pasos adicionales que son importantes tomar:

  • Si es necesario, utilice el concepto de "encabezados privados". Es decir, archivos de encabezado que son requeridos por varios archivos de origen, pero nunca requeridos por el interfaz pública. Esto podría ser un archivo con funciones en línea comunes, macros o constantes internas.
  • Separe su interfaz pública de su implementación privada a nivel de sistema de archivos. Tiendo a usar subdirectorios include/ y src/ en mis proyectos C o C++, donde include/ tiene todos mis encabezados públicos, y src/ tiene todas mis fuentes. y encabezados privados.

Recomendaría encontrar una copia del libro de John Lakos Diseño de Software C++ a gran escala. Es un un libro bastante fuerte, pero si solo hojeas algunas de sus discusiones sobre arquitectura física, aprenderás mucho.

 65
Author: Tom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-06 08:35:56

Echa un vistazo a los estándares de codificación C y C++ en el NASA Goddard Space Flight Center. La única regla que noté especialmente en el estándar C y que he adoptado en mi propio código es la que impone la naturaleza 'independiente' de los archivos de encabezado. En el archivo de implementación xxx.cpp para el encabezado xxx.h, asegúrese de que xxx. h sea el primer encabezado incluido. Si el encabezado no es autónomo en cualquier momento, la compilación fallará. Es un bellamente simple y eficaz regla.

El único momento en que no se es si el puerto entre las máquinas, y el xxx.h encabezado incluye, digamos, <pqr.h> pero <pqr.h> requiere instalaciones que pasan a estar disponibles por un header <abc.h> en la plataforma original (por lo que <pqr.h> incluye <abc.h>), pero las instalaciones no están disponibles por <abc.h> en la otra plataforma (están en def.h en su lugar, pero <pqr.h> no incluyen <def.h>). Esto no es culpa de la regla, y el problema es más fácil de diagnosticar y solucionar si se sigue la regla.

 8
Author: Jonathan Leffler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-06 11:11:25

Compruebe la sección del archivo de encabezado en Guía de estilo de Google

 6
Author: yesraaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-13 03:28:38

¡La respuesta de Tom es excelente!

Lo único que añadiría es nunca tener "usando declaraciones" en los archivos de encabezado. Solo se deben permitir en archivos de implementación, por ejemplo, foo.cpp.

La lógica para esto está bien descrita en el excelente libro "Accelerated C++" ( Amazon link - sanitised for script kiddie link nazis)

 5
Author: Rob Wells,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:46:25

Un punto más además de los otros aquí:

No incluya ninguna definición privada en un archivo de inclusión. E. g. any definición que solo se utiliza en xxx.cpp debería estar en xxx.cpp, no xxx. h.

Parece obvio, pero lo veo frecuentemente.

 3
Author: Steve Fallows,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-07 21:58:16

Me gustaría añadir una práctica muy buena (tanto en C como en C++) que a menudo se abandona:

Foo.c

#include "foo.h" // always the first directive

Cualquier otro encabezado necesario debe seguir, luego codificar. El punto es que casi siempre necesita ese encabezado para esta unidad de compilación de todos modos y incluirlo como una primera directiva garantiza que el encabezado siga siendo autosuficiente (si no lo es, habrá errores). Esto es especialmente cierto para los encabezados públicos.

Si en algún momento necesitas poner algo antes de esto inclusión de encabezado (excepto comentarios, por supuesto), entonces es probable que estés haciendo algo mal. A menos que realmente sepas lo que estás haciendo... lo que lleva a otra regla más crucial = > ¡comenta tus hacks !

 3
Author: Alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-30 07:04:52