c++ - Los nombres incluyen guardias
c-preprocessor include-guards (9)
¿Cómo se nombran normalmente las guardias de C ++? Tiendo a ver esto mucho
#ifndef FOO_H
#define FOO_H
// ...
#endif
Sin embargo, no creo que sea muy intuitivo. Sin ver el nombre del archivo, es difícil decir para qué está FOO_H
y a qué se refiere su nombre.
¿Qué se considera la mejor práctica?
Como se mencionó anteriormente, una convención muy común es usar la versión en mayúsculas del nombre y el punto reemplazado por un guión bajo: foo.h -> FOO_H
Sin embargo, esto puede llevar a colisiones de nombres con nombres simples y / o comunes. Por esta razón, el encabezado generado automáticamente como stdafx.h en proyectos de Visual C C ++ no vacíos agrega una cadena aleatoria, como:
#ifndef FOO_H__NsknZfLkajnTFBpHIhKS
#define FOO_H__NsknZfLkajnTFBpHIhKS
#endif
http://www.random.org/strings/ es un generador aleatorio útil para esto.
Además, si el archivo es parte de algún submódulo, o su contenido reside en un espacio de nombres específico, tiendo a agregar eso también a la guardia:
#ifndef SOMECOMPONENT_FOO_H__NsknZfLkajnTFBpHIhKS
#define SOMECOMPONENT_FOO_H__NsknZfLkajnTFBpHIhKS
namespace somecomponent
{
...
}
#endif
Desde mi propia experiencia, la convención es nombrar los guardias de inclusión después del archivo de encabezado que los contiene, con la excepción de que el nombre está todo en mayúsculas y el período se reemplaza con un guión bajo.
Así que test.h
convierte en TEST_H
.
Ejemplos reales de esto incluyen Qt Creator, que sigue esta convención cuando se generan automáticamente archivos de encabezado de clase.
Mira el código que # incluye tu encabezado.
Si es algo como:
#include "mylib/myheader.h"
mylib/myheader.h
ya es un nombre único. Solo capitaliza y reemplaza / y. con _
#define MYLIB_MYHEADER_H
Si tiene dos encabezados en su ruta de inclusión con el mismo nombre en relación con la ruta de inclusión, ya tiene una colisión en ese nivel.
Normalmente uso algo como FOO_H_INCLUDED_
. Algunos encabezados (de Microsoft) tienen lo que se parece mucho a una representación de cadena de un GUID, pero nunca he necesitado nada tan detallado.
Por lo general miro a qué hora es y simplemente lo agrego al final, es decir, FOO_H_248
, es una precaución adicional, y nunca tendrás que recordarlo de todos modos, por lo que no debes preocuparte por el hecho de que es críptico. .
Por lo general, la gente lo hace por nombre de archivo, de modo que el código de cada archivo solo se compila y agrega una vez. Podría hacer FOO_H lo que quiera, pero casi todo lo que he codificado o visto ha usado el nombre del archivo. Solo asegúrate de que sea único porque no quieres que tu FOO_H esté en conflicto con el FOO_H de otra persona.
Reemplace FOO_H
con FOO_H_INCLUDED
y queda más claro.
Tomado directamente de la guía de estilo de google :
Todos los archivos de encabezado deben tener guardias #define para evitar la inclusión múltiple. El formato del nombre del símbolo debe ser <PROJECT> _ <PATH> _ <FILE> _H_. Para garantizar la singularidad, deben basarse en la ruta completa en el árbol de origen de un proyecto. Por ejemplo, el archivo foo / src / bar / baz.h en el proyecto foo debería tener la siguiente protección:
#ifndef FOO_BAR_BAZ_H_ #define FOO_BAR_BAZ_H_ ... #endif // FOO_BAR_BAZ_H_
Utilizo este estilo en mis propios proyectos.
Yo personalmente sigo la recomendación de Boost. Es quizás una de las colecciones más grandes de bibliotecas de C ++ de buena calidad y no tienen problemas.
Va como:
<project>_<path_part1>_..._<path_partN>_<file>_<extension>_INCLUDED
// include/pet/project/file.hpp
#ifndef PET_PROJECT_FILE_HPP_INCLUDED
cual es:
- legal (tenga en cuenta que comenzar por
_[AZ]
o que contiene__
no lo es) - fácil de generar
- garantizado para ser único (como un protector incluido) dentro de un proyecto (de lo contrario tiene dos archivos en el mismo lugar)
- garantizado que no se utilizará para ninguna otra cosa (si finalizas otra macro con
INCLUDED
te estás echando a perder por una pelea)
He leído sobre GUID pero se ven raros.
Y obviamente prefiero que todos los compiladores implementen #pragma once
(o mejor, #pragma multiple
y "once" sean el comportamiento predeterminado ...)