Pregunta

Esta pregunta es uno de los varios que discuten las convenciones de nombres para C ++ incluyen guardias. La persona que hace esa pregunta piensa que esta convención de nombres:

#ifndef FOO_H
#define FOO_H

// ...

#endif

es un poco no intuitivo cuando se toma solo (lo que sí FOO_H medio?) Y tiendo a estar de acuerdo.

Otros dicen eso, salvo la necesidad de agregar más cosas para una mejor evitación de colisión (como PROJECTNAME_FOO_H_SDFFGH69876GF), el nombre FOO_H Está bien porque está claro en su contexto cuál es su propósito (es decir, es al comienzo de los archivos del mismo nombre y está claro que es una guardia de incluido).

Podría comprar esto si el único propósito de tener FOO_H sería protegerse contra la inclusión múltiple, pero hay condiciones para las cuales me gustaría tener FOO_H ¿En otra parte de los archivos? Creo que la compilación condicional sería una buena razón, en cuyo caso nombrarlo como algo así como FOO_H_INCLUDED sería más claro.

¿Hay usos directivos de esto similares a esto, o debo evitar la reutilización de los guardias de incluido?

¿Fue útil?

Solución

Creo que la pregunta es defectuosa en sí misma. El término incluye guardias se refiere a #defines y cheques para #defined en el uso particular de protegiendo contra la inclusión múltiple, que es tanto para decir que es el único uso para eso.

Ahora que se toma un poco más en general, las define y la compilación condicional se pueden usar para otras cosas, como escribir bits de código que dependan de la plataforma y solo se compilarán en algunas circunstancias ...

Ya sea FOO_H o FOO_H_INCLUDED es mejor, siempre diré que el último es el más expresivo, y luego volveré a vi y escribir FOO_H En mi próximo foo.h encabezamiento. Nuevamente, como mencioné en un comentario sobre la otra pregunta, te acostumbres al patrón:

#ifndef XXXXXXXXX
#define XXXXXXXXX

#endif

Como los dos primeros y la última línea en un archivo y terminas notando. Eso es hasta que hace un mordisco si ha reutilizado el mismo nombre ...

Otros consejos

A veces, uso esto para archivos de encabezado de "implementación". El esquema de nombres real para los guardias puede diferir.

#ifndef FOO_IMPL_H
#define FOO_IMPL_H

#ifndef FOO_H
#error Don't include this directly
#endif

// Ugly implementation of the stuff in foo.h, with an uncountable
// number of template and typename keywords

#endif 

En mi opinión, incluir los guardias deben incluir guardias y nada más. Si desea una compilación condicional, definiría algo más. Si estabas tirando #if defined(FOO_H) En su código, creo que la gente encontraría esto extraño desde _H Por lo general, indica un guardia de incluido.

Sin embargo, una cosa que puedo pensar es verificar si el archivo ya se ha incluido (¡duh!) Para que no tenga que incluir el archivo usted mismo. No estoy seguro de si esto aceleraría la compilación o no, en comparación con las declaraciones hacia adelante o #pragma once

En main.cpp:

#include "bar.h" // comment this line to see the difference
#include "foo.h"

int main()
{
    return 0;
}

En bar.h:

#ifndef BAR_H
#define BAR_H

class BarClass
{
};

#endif

En foo.h:

#ifndef FOO_H
#define FOO_H

#if !defined(BAR_H)
#error bar h was not included // forgot how to do compiler warnings...
#include "bar.h" // we should include the file
#else
#error bar h was included // same thing, should be changed to warning
#endif

// do something with BarClass

#endif FOO_H

Creo que la compilación condicional sería una buena razón, en cuyo caso nombrarlo como Foo_H_included sería más claro.

Solo veo un uso muy estrecho aquí para evitar incluir un encabezado cuando solo necesita una declaración delantera, pero quiero omitir las declaraciones de avance si el encabezado se ha incluido previamente.

Sin embargo, este no es un cuello de botella en la compilación de C ++ hoy, y la confusión adicional sobre tener siempre las declaraciones delantera o siempre incluir el encabezado no vale la pena.

Incluso si necesitaras toneladas, y me refiero a cientos de miles de líneas de estas declaraciones hacia adelante, para que valiera la pena, estarías mejor con un encabezado dedicado, similar au003Ciosfwd> , en lugar de mantener esto en múltiples lugares.

Para reutilizar: a menos que todo el contenido del archivo esté rodeado por IFNDEF/Define/Endif, entonces FOO_H ¿No es realmente un expediente Incluye Guard, es solo proteger parte de un archivo. Así que posiblemente no debería llevarse el nombre de todo el archivo. La inclusión recursiva del mismo archivo es una situación en la que esto puede surgir.

Dicho esto, sospecho que aun así, debería ser bastante obvio para qué es lo que es la definición (de todos modos, más obvio que cualquier cosa que esté haciendo que esté haciendo que no sea simple incluye proteger). En cualquier lugar donde vea el patrón ifndef foo / define foo, o incluso solo ifndef foo / define muchas cosas, un comentario simple puede hacer que el significado de Foo sea obvio si aún no está.

Si alguna parte de la pregunta es si el token FOO_H alguna vez podría usarse para otro propósito: supongo que si tiene un archivo en algún lugar llamado uppercase.h que usa UPPERCASE_H Como guardia de incluido, entonces eso podría chocar con el de alguien rot13.h, que contiene #define UPPERCASE_A ('N'), etc. Ejemplo tonto, pero si estuviera definiendo las propiedades de las letras en un archivo de encabezado, entonces no es ridículo pensar que algunos de ellos podrían terminar en _H.

De manera más realista, he tenido proyectos con archivos que tienen el mismo nombre de base en diferentes directorios.

Entonces, independientemente del tema del contexto y la reutilización, no usaría FOO_H como un guardia incluido.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top