2010-12-25 9 views

Respuesta

7

Algunas razones:

(1) los tiempos de construcción incremental

Cuando los proyectos se hacen más grandes, gestionando el tiempo de construcción es problemático especialmente para proyectos de C++. Construir 1 o 5 minutos después de un cambio menor hace una gran diferencia. Esto es enfatizado por la mayoría de los cambios en proyectos grandes que son pequeños y requieren una gran cantidad de pruebas. Agregue a eso cualquier intento de TDD y refactorización, y usted es un babosazo con zapatos sicilianos.

Dividir en encabezado y cuerpo, y moverlo a libs mejora tremendamente los tiempos de compilación.

(2) Estática
Para muchas cosas que hay una sola instancia de un tipo, es decir

// .cpp 
static Foo foo; 

No hay manera (que yo sepa) que permite esto en un Header solo proyecto. Las soluciones específicas del compilador son limitadas, p. __declspec(selectany) en MSVC está limitado a los tipos de POD.

(3) Implementación ocultar
.cpp/.h separación es la única manera de separar claramente una interfaz pública de los detalles de implementación. Puede lanzar miembros de clase en una sección private, pero eso no funciona para otras entidades. (Incluso la separación del encabezado/cuerpo tiene fugas a menos que agregue técnicas adicionales como PIMPL, por lo que este argumento es un IMO débil, pero, de nuevo, en un proyecto grande me extrañaría mucho este método eficiente si imperfecto).


Gran pregunta, de todos modos - que ha reconocido que hay algo en conflicto con la C/C++ construir el modelo, que considero una antigua reliquia de consecuencias terribles.

Debe probar qué tan lejos puede empujar un modelo "solo encabezado" (o, al menos, un "casi solo encabezados", para permitir estáticos). Puede llegar muy lejos; también sería interesante escuchar a las personas que lo han intentado.

Puede valer la pena intentar usar bibliotecas estáticas para separar y encapsular implementaciones, y de lo contrario mantener todo el código en los encabezados. Puedo ver algunos problemas con eso, pero es que nuestro modus operandi actual no tiene problemas.

+4

+1 para llamar al modelo C/C++ build/link que realmente es bastante calamitoso –

2

Los archivos de encabezado (.h) están destinados a ser utilizados para definir la interfaz de manera que sus clases y código se puedan usar en otras unidades de traducción. Si coloca la implementación en el archivo .h, terminará con varias copias del mismo código, compiladas en cada unidad de traducción que incluye ese archivo .h. Eso frustra el punto de dividir tu código en pequeños pedazos que se pueden estudiar y desarrollar de forma aislada.

+0

Creo que aún se puede hacer, puede poner la interfaz pública en encabezados que incluyen los "encabezados de implementación", de la misma forma que aumenta con las subcarpetas 'details \'. Sin un uso intensivo de interfaces, la separación .h/.cpp no ​​coincide muy bien con la separación interfaz/implementación. – peterchen

3

Usted podría poner todo su código en archivos .h. Contrariamente a la creencia popular, esto no duplicará el código en sus archivos .obj. Los compiladores modernos son mucho más inteligentes que eso.

Sin embargo, la compilación es un problema. Si tiene 20 archivos .h incluidos en main.cpp, compilar main.cpp llevará un tiempo. Y se volverá a compilar, incluidos los 20 archivos .h de implementación, cada vez que cambie alguno de los archivos incluidos.

Luego está el estilo. Simplemente me parece mal. Pero esta es una cuestión de preferencia.

Luego hay referencias. Si ClassA usa ClassB, y ClassB usa ClassA, ¿cuál incluye usted primero?

+0

No veo dónde entran los compiladores modernos. Una vez que tenga varias unidades de traducción que incluyan archivos de encabezado con implementación, duplicará el código en los archivos del objeto. Sí, en teoría, esta duplicación podría eliminarse, pero tendría que hacerla el vinculador en lugar del compilador. –

+0

Su suposición sobre las funciones del enlazador y del compilador está bastante desactualizada. La generación de código de tiempo de enlace se ha utilizado ampliamente durante una década. Una manera descuidada de decirlo sería que con LTCG el compilador es solo un preprocesador sofisticado: los archivos .obj en realidad no contienen código de máquina. Y eliminar un código duplicado (e innecesario, etc.) es un hecho. – martona

+0

todo suena muy, muy inteligente, ¡es una lástima que sea necesario para hacer frente al anticuado modelo de construcción de C/C++! –

Cuestiones relacionadas