Including header files in C/C++ more than once [duplicate]

杀马特。学长 韩版系。学妹 提交于 2019-11-26 13:48:15

问题


This question already has an answer here:

  • Is there any situation where you wouldn't want include guards? 6 answers

Is it ever useful to include a header file more than once in C or C++?

If the mechanism is never used, why would the compiler ever worry about including a file twice; if it really were useless, wouldn't it be more convenient if newer compilers made sure every header is included only once?

Edit:

I understand that there are standard ways of doing things like include guards and pragma once, but why should you have to specify even that? Shouldn't it be the default behavior of the compiler to include files only once?


回答1:


Yes, it's useful when generating code with the preprocessor, or doing tricks like Boost.PP does.

For an example, see X Macros. The basic idea is that the file contains the body of the macro and you #define the arguments and then #include it. Here's a contrived example:

macro.xpp

std::cout << MESSAGE;
#undef MESSAGE

file.cpp:

int main() {
# define MESSAGE "hello world"
# include "macro.xpp"
}

This also allows you to use #if and friends on the arguments, something that normal macros can't do.




回答2:


Yes, including a header more than once can be useful (though it is fairly unusual). The canonical example is <assert.h>, which defines asssert differently depending on whether NDEBUG is defined or not. As such, it can make sense to include it, then have a (usually conditional) definition of NDEBUG, followed by including it again, with (at least potentially) different definitions of assert:

The assert macro is redefined according to the current state of NDEBUG each time that <assert.h> is included1.

Most headers, however, go to some pains to be idempotent (i.e., to have the same effects no matter how often they're included).


1C99, §7.2/1.




回答3:


A typical example (untested) - point being that it factors a list of enumerations so they appear consistently in an enum and in streaming code:

// 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>";
}



回答4:


Yes it would be more convenient only to include it once and that is why you use #pragma once . in C++ :)

Edit:

Note: #pragma once is non-portable. You can use

#ifndef FILENAME_H
#define FILENAME_H

in top of your header files instead if you want it to be portable.




回答5:


Multiple inclusion can be used whenever you need some "boring" code generation that you don't want to maintain by hand, again and again.

The classic example would be a C/C++ enum and the corresponding strings, which more or less looks like this:

// 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



回答6:


#ifndef _INC_HEADER_
#define _INC_HEADER_

//header code

#endif

Where HEADER is the header's name

eg. main_win.h will be _INC_MAIN_WIN_



来源:https://stackoverflow.com/questions/10877494/including-header-files-in-c-c-more-than-once

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!