c++ - que - incluir un archivo c en otro
Incluir archivos de encabezado en C/C++ más de una vez (6)
Esta pregunta ya tiene una respuesta aquí:
¿Alguna vez es útil incluir un archivo de encabezado más de una vez en C o C ++?
Si el mecanismo nunca se usa, ¿por qué el compilador alguna vez se preocuparía de incluir un archivo dos veces? si realmente fuera inútil, ¿no sería más conveniente si los compiladores más nuevos se aseguraran de que cada encabezado se incluyera solo una vez?
Editar:
Entiendo que hay formas estándar de hacer cosas como incluir guardias y pragma una vez , pero ¿por qué deberías especificar incluso eso? ¿No debería ser el comportamiento predeterminado del compilador incluir archivos solo una vez?
La inclusión múltiple se puede usar siempre que necesite una generación de código "aburrido" que no desee mantener a mano, una y otra vez.
El ejemplo clásico sería una enum C / C ++ y las cadenas correspondientes, que más o menos se parece a esto:
// MYENUM_VALUES.H
MYENUMVALUE(a)
MYENUMVALUE(b)
MYENUMVALUE(c)
MYENUMVALUE(d)
// MYENUM.H
#define MYENUMVALUE(x) x,
enum MyEnum
{
#include "MYENUM_VALUES.H"
}
#undef MYENUMVALUE
// MYENUMTOSTRING.C
#define MYENUMVALUE(x) case x : return #x;
const char * MyEnumToString(MyEnum val)
{
switch (val)
{
#include "MYENUM_VALUES.H"
default return "unknown";
}
}
#undef MYENUMVALUE
Sí, es útil al generar código con el preprocesador o al hacer trucos como Boost.PP.
Para un ejemplo, vea X Macros. La idea básica es que el archivo contiene el cuerpo de la macro y usted #define
los argumentos y luego #include
it. Aquí hay un ejemplo artificial:
macro.xpp
std::cout << MESSAGE;
#undef MESSAGE
file.cpp:
int main() {
# define MESSAGE "hello world"
# include "macro.xpp"
}
Esto también le permite usar #if
y amigos en los argumentos, algo que las macros normales no pueden hacer.
Sí, incluir un encabezado más de una vez puede ser útil (aunque es bastante inusual). El ejemplo canónico es <assert.h>
, que define asssert
diferente según si está definido o no NDEBUG
. Como tal, puede tener sentido incluirlo, luego tener una definición (normalmente condicional) de NDEBUG, seguido de incluirlo de nuevo, con (al menos potencialmente) diferentes definiciones de assert
:
La macro
assert
se redefine de acuerdo con el estado actual deNDEBUG
cada vez que se incluye<assert.h>
1 .
La mayoría de los encabezados, sin embargo, hacen algunos esfuerzos para ser idempotentes (es decir, para tener los mismos efectos sin importar la frecuencia con la que estén incluidos).
1 C99, §7.2 / 1.
Sí, sería más conveniente solo incluirlo una vez y es por eso que usa #pragma una vez. en C ++ :)
Editar:
Nota: #pragma una vez no es portátil. Puedes usar
#ifndef FILENAME_H
#define FILENAME_H
en la parte superior de los archivos de encabezado en su lugar si desea que sea portátil.
Un ejemplo típico (no probado): el punto es que determina una lista de enumeraciones para que aparezcan consistentemente en una enum
y en un código de transmisión:
// states.h
X(Uninitialised)
X(Initialised)
X(Running)
X(Complete)
X(Shutdown)
// app.c++
#if defined(X)
# error X is already defined
#endif
enum States {
#define X(TAG) TAG,
#include "states.h"
#undef X
Extra_So_Trailing_Comma_Ignored
};
std::ostream& operator<<(std::ostream& os, const States& state)
{
#define X(TAG) if (state == TAG) return os << #TAG;
#include "states.h"
#undef X
return os << "<Invalid-State>";
}
#ifndef _INC_HEADER_
#define _INC_HEADER_
//header code
#endif
Donde HEADER
es el nombre del encabezado
p.ej. main_win.h
será _INC_MAIN_WIN_