c++ - otro - incluir header en c
Mejores prácticas para el uso de archivos de cabecera C++ (5)
El orden de los guardias de inclusión y los comentarios es puramente una cuestión de estilo; no tendrá ningún efecto mensurable en la velocidad de compilación.
Los espacios de nombres deben usarse en los archivos de cabecera para declarar funciones, clases, globales, etc. Lo que no se debe hacer es usar declaraciones en los archivos de encabezado: es imposible desusar algo en un archivo fuente que lo incluye, y no se debe forzar incluidos para agregar cosas adicionales al alcance global. Si necesita usar elementos de otros espacios de nombres en sus encabezados, califique completamente cada nombre. A veces puede ser doloroso, pero es realmente lo correcto.
Ejemplos:
// WRONG!
using namespace std;
class MyClass
{
string stringVar;
};
// RIGHT
class MyClass
{
std::string stringVar;
};
En cuanto a las declaraciones avanzadas de clases en otros espacios de nombres, lo tienes exactamente correcto. Recuerde siempre calificar AnotherFoo
como AnotherNameSpace::AnotherFoo
cuando lo referencia dentro de su encabezado. De hecho, las declaraciones directas son la única forma de romper las dependencias cíclicas.
Tengo las siguientes dudas sobre el uso de archivos de encabezado.
1 - Incluir guardias colocando después de los comentarios
/* Copyright Note and licence information (multiple lines) */
#ifndef FOO_H
#define FOO_H
// Header file contents
#endif
Herb Sutter dice en su libro "Estándares de codificación C ++" que un código como el anterior es problemático. Él está diciendo que las declaraciones "#ifndef" deberían aparecer en la primera línea del archivo de encabezado. No lo he sentido tan convincente. ¿Siguen ustedes chicos / chicas en los archivos de encabezado?
2 - Uso de espacios de nombres en archivos de encabezado
#ifndef FOO_H
#define FOO_H
namespace FooNameSpace{
// Header file contents
}
#endif
¿El código anterior usa la práctica correcta? Quiero decir, ¿usas espacios de nombres en los archivos de encabezado? Sé por qué importar un espacio de nombres en el archivo de encabezado no tiene sentido, pero ¿qué pasa con una declaración como la anterior?
Si el anterior es el método correcto, ¿cómo se hace " forward declaration " de una clase que está en otro espacio de nombres? Es como
#ifndef FOO_H
#define FOO_H
namespace AnotherNameSpace{
class AnotherFoo; // forward declaration
}
namespace FooNameSpace{
// Use AnotherFoo here
}
#endif
La " declaración directa " es el único método para evitar la " dependencia cíclica ", ¿correcto?
He oído que tener comentarios antes del protector de inclusión puede hacer que algunos compiladores pierdan una optimización. Si el guardia es lo primero, el compilador puede reconocer el modismo y no molestarse en abrir el encabezado para los siguientes. En mi propio código, los comentarios normalmente preceden al protector de inclusión. Nunca me he molestado en probar para ver si esto tiene algún impacto o no. Y probablemente nunca lo haré (pero si alguien más lo hace, estaría interesado en los resultados).
Por supuesto, los encabezados deben incorporar espacios de nombres; de lo contrario, nada útil podría estar dentro de un espacio de nombres. Sin embargo, como mencionaste, los encabezados no deberían ''importar'' (a falta de una mejor palabra) espacios de nombres en una unidad de compilación con una directiva ''
using
''.
No creo que agregar comentarios tenga un impacto en el rendimiento, como lo señala la respuesta de Adam a esta publicación.
He usado espacios de nombres en los archivos de encabezado, ¿qué pasa si defines tu propia clase de cadena, por lo que entraría en conflicto con la clase de cadena de espacio de nombres std?
Usar la palabra clave "usar" no es incorrecto (ya que le da mucha comodidad y mucho menos para escribir antes de todas sus variables)
1) Dado que los comentarios en realidad no hacen nada, dudo que importe mucho. Aunque técnicamente, #include copiar y pegar, por lo que poner los comentarios fuera de los resguardos del encabezado puede significar más trabajo para el preprocesador. No sé si la mayoría de los compiladores son lo suficientemente inteligentes como para optimizar esto (es decir, si eliminan los comentarios antes del paso del preprocesador), pero probablemente no se darán cuenta hasta que lleguen a decenas de miles de archivos de encabezado.
2) Eso es correcto. Si quiere poner una clase dentro de un espacio de nombres, y esa clase va a ser declarada en un archivo de encabezado, entonces debe declararse dentro del espacio de nombres, que por lo tanto debe estar en el archivo de encabezado. Y sí, así es como declaraste exactamente. Y sí, es la herramienta principal para evitar la dependencia cíclica (también puede cambiar su diseño, pero no hay nada de malo en la ciclicidad en principio, siempre que las dos clases en cuestión se refieran entre sí por referencia o puntero y no llamen a ningún método) .
Respecto al # 1, no estoy al tanto de ningún argumento concreto a favor o en contra. Muchas empresas tienen una política en la que el aviso de copyright debe ser el primer elemento del archivo ANTES de cualquier otra cosa o de cualquier código significativo (tal vez supongamos que leerá los derechos de autor antes de absorber cualquier código). Para ese propósito, #IFNDEF ya es código. Desde el punto de vista de la usabilidad, tiene sentido poner los derechos de autor primero porque el ojo los ignora. Sin embargo, cualquier cosa que describa el módulo debería venir después del #ifndef en mi opinión.