Diseño de archivos de encabezado C ++: ¿como definir una API?

8

Soy un poco nuevo en el desarrollo de software a gran escala en C ++, y me preguntaba sobre el lado del diseño de las cosas.

Estaba leyendo esta pregunta y pensé que, en general, una vez que superamos las definiciones constantes y otros asuntos triviales, los archivos de encabezado de C ++ son solo definiciones de API :

Definen lo que otros programadores (o usted mismo de otros módulos) podrán usar (clases, funciones públicas), pero no se debe definir ninguna clase o función privada. Es como si el archivo de encabezado define las abstracciones (interfaces ...) y el archivo de origen lo implementa. Una vez que se compila el archivo fuente, los detalles de implementación se ocultan y siguen siendo los encabezados disponibles públicamente que definen lo que puede hacer el módulo.

Sentí que esta vista de la separación del archivo de cabecera / fuente era mucho más fácil de entender y seguir que las explicaciones habituales, ya que puedes pensar que "sería XXXmaterial de API disponible públicamente, o es un detalle para hacer salchichas que se esconde en un archivo fuente no revelado? "

¿Es mi modelo mental de archivos de encabezado más o menos correcto? Qué me perdí ?

Jiby
fuente
También se fijan en UML para un sistema creado para el software de diseño ayuda - sus clases muestran métodos de la API y los datos (atributos) en los diagramas de clases
gbjbaanb
¡Oh créeme, sé sobre UML! = p Es solo la forma en C ++ de pensar que tengo problemas para entenderlo. "Vengo del mundo de Python", con todos los sesgos de pensar "¿Por qué un lenguaje necesitaría archivos de encabezado?" =)
Jiby

Respuestas:

10

No es un mal modelo mental para usar como guía, pero desafortunadamente por razones históricas / técnicas, los encabezados de C ++ combinan la interfaz y la implementación de manera que este modelo mental simple no captura completamente.

Para tomar buenas decisiones de diseño físico cuando las cosas se vuelven un poco más complejas, generalmente es necesario comprender cómo funcionan los encabezados en C ++ a un nivel más detallado.

Para dar un ejemplo: desde su vista API, un archivo de encabezado no debe incluir la definición de una clase de implementación privada. Sin embargo, en la práctica, tales definiciones de clase a menudo aparecerán en un archivo de encabezado ya que el compilador necesitará saber su tamaño si están contenidas en clases públicas. Existen técnicas para romper este tipo de dependencia, pero generalmente imponen un costo en términos de complejidad del código, rendimiento o ambos. Comprender cuándo es apropiado usar una de estas técnicas requiere una comprensión más profunda de cómo funcionan los encabezados en C ++.

Mattnewport
fuente
Estaba pensando en las definiciones avanzadas de clases privadas: ¿podemos hacer trampa al colocarlas en un archivo de encabezado "oculto" separado e incluirlas? De esta manera, mantendría el "encabezado API simple" y uno "trucos privados sucios". Sin embargo, no estoy seguro de que sirva de mucho.
Jiby
@Jiby Un encabezado de "detalle" separado es una forma bastante común de dividir los detalles de implementación privados, así que sí, puede ser un buen enfoque. También es bastante común poner detalles de implementación en un detailespacio de nombres anidado para que no contaminen el espacio de nombres de la biblioteca principal y dejar en claro que no están destinados a ser utilizados directamente.
mattnewport
3

Prácticamente, hay poca diferencia entre un archivo de encabezado y una interfaz como la usan otros idiomas para la parte principal. Obviamente, aunque existen diferencias en la implementación en que el encabezado también contendrá información privada, pero fundamentalmente se utilizan para describir las características que proporcionará la clase o el módulo.

En cierto modo, también es un modelo mental de estructuras de datos combinadas con la API, por lo que puede ser más útil cuando está haciendo el tipo de diseño inicial que describe.

Idealmente, un encabezado que define una API contendría solo la interfaz pura, pero como C ++ no tiene una ABI, esto realmente no importa. Si crea un sistema de nivel superior que proporciona una interfaz de cliente pura, utilizará un mecanismo diferente, como un IDL o WSDL para definirlo de todos modos.

gbjbaanb
fuente
2
Ver también:
Idioma de
-1

El archivo de encabezado como una interfaz pura funciona más o menos bien con las clases. Tan pronto como aparecen las plantillas, este modelo deja de funcionar en absoluto. Las plantillas no son compilables, y toda la implementación de la plantilla debe aparecer en el encabezado.

usuario58697
fuente
¿Podemos hacer trampa escribiendo código relacionado con la plantilla en un encabezado separado e incluyéndolo?
Jiby