tags:

views:

176

answers:

7
#include "DLLDefines.h"
#include "DLLDefines.h"

The above actually passed compilation, but why?

+4  A: 

Probably you have some #define in DLLDefines.h around your code that prevents it from being included twice.

#ifndef DLLDEFINES_H
#define DLLDEFINES_H
// your code
#endif
Zaki
Nitpick: This technique doesn't prevent it from being included twice; it makes it safe to include it multiple times.
Charles Bailey
@Charles: it prevents the code in the header from being read twice, which is what normally is meant with include'ing a file.
rubenvb
Indeed, I wasn't sure how to say it without overcomplicating the explanation. The preprocessor will ignore the contents inside the #ifndef the second time the file is included.
Zaki
@rubenvb: I understand that, I just feel that it's important not to make `#include` seem more magic than it is when the question asker obviously needs to understand the basics. Being strictly accurate _may_ help to avoid confusion.
Charles Bailey
+7  A: 

It depends on the header file; there is no language restriction on multiple includes of the same file.

Some files are designed to be included multiple times (e.g. <assert.h> can be included multiple times to turn 'on' and 'off' assert).

Many files are safe to be included multiple times because they have include guards, others are not and should be included only once in a translation unit or even a program.

Charles Bailey
+4  A: 

include has nothing to do with the C or C++ language. It is a directive to the preprocessor to bring in a file. The preprocessor doesn't care what file is brought in and it shouldn't. It might be perfectly acceptable to do this:

void Foo::SomeFunc(int cond)
{
    switch (cond) {
    case kThisCase:
#include "longFirstCase.h"
        break;
    case kSecondCase:
#include "longSecondCase.h"
        break;
    case kThirdCase:
#include "longFirstCase.h"
#include "longSecondCase.h"
        break;
    }
}

I have seen the same file included several times as a configuration mechanism as well.

Granted, there are a number of ways to factor that example that are better, but the point is that there may be perfectly good reasons why you would want to and therefore no restriction on the use.

plinth
How do you expect this to work ? #Including things depending on runtime information ?
Shautieh
@Shautieh, `#include` inserts the source file verbatim. Presumably the files `longFirstCase.h` and `longSecondCase.h` contain C code meant to be inside the `switch` statement.
strager
@Shautieh like strager said, it pastes the code into the file where the #include is written. As an example this technique is often used so as to include parts of autogenerated code.
Stephane Rolland
It may make some sense to include some cpp code, but header files ? I'm not saying it won't work, but it doesn't seem "right" to me..
Shautieh
@Shautieh: the extension in a filename doesn't affect `#include`. In this imaginary case, the `.h` files must contain some lines of code intended to be dropped into the middle of a function. Granted, most programmers would give the file a different extension, perhaps `.inc`.
Steve Jessop
.h is just a file extension. You coudl rename them to .cpp and #include them, but .cpp implies the file can be compile all by itself, and some build systems will try to compile all .cpp files they find which probably would fail here since the files don't contain 'complete' code, just fragments.
SoapBox
The preprocessor is part of the C and C++ languages.
Dennis Zickefoose
@Steve : if one really have to include implementations this way, giving an extension such as .inc would be a lesser evil indeed. @SoapBox : .h isn't "just" an extension. It may be so for the preprocessor, but it's against all sensible conventions to use it like this and it's going to bite the developer sooner or later for this reason.
Shautieh
+1  A: 

It's called an include guard.

#ifndef GRANDFATHER_H
#define GRANDFATHER_H

struct foo {
    int member;
};

#endif

Quote from Wikipedia:

In the C and C++ programming languages, an #include guard, sometimes called a macro guard, is a particular construct used to avoid the problem of double inclusion when dealing with the #include directive. The addition of #include guards to a header file is one way to make that file idempotent.

See link above for more information.

JustBoo
+2  A: 

As long as the multiple inclusion of header files do not violate ODR (One definition Rule) $3.2, the code is well-formed.

Chubsdad
A: 

DLLDefines.h may also have #pragma once at the top, #pragma once ensures that file gets included only once.

bjskishore123
That's a Microsoft only extension, IIRC.
JustBoo
+3  A: 

Well, it's legal because it has to be legal. Because you often include the same header multiple times without even realizing it.

You might include two headers in a .cpp file, each of which include a number of files, some of which might be included by both.

For example, all the standard library headers (say, string or vector for example) are probably included in most of your headers. So you quickly end up with the same header being indirectly included multiple times in the same .cpp file.

So in short, it has to work, or all C++ code would fall apart.

As for how it works, usually through include guards. Remember that #include just performs a simple copy/paste: it inserts the contents of the header file at the #include site.

So let's say you have a header file header.h with the following contents:

class MyClass {};

now let's create a cpp file which includes it twice:

#include "header.h"
#include "header.h"

the preprocessor expands this to:

class MyClass {};
class MyClass {};

which obviously causes an error: the same class is defined twice. So that doesn't work. Instead, let's modify the header to contain include guards:

#ifndef HEADER_H
#define HEADER_H

class MyClass {};

#endif

Now, if we include it twice, we get this:

#ifndef HEADER_H
#define HEADER_H

class MyClass {};

#endif

#ifndef HEADER_H
#define HEADER_H

class MyClass {};

#endif

And this is what happens when the preprocessor processes it:

#ifndef HEADER_H // HEADER_H is not defined, so we enter the "if" block
#define HEADER_H // HEADER_H is now defined

class MyClass {};// MyClass is now defined

#endif           // leaving the "if" block

#ifndef HEADER_H // HEADER_H *is* defined, so we do *not* enter the "if" block
//#define HEADER_H
//
//class MyClass {};
//
#endif           // end of the skipped "if" block

So, the end result is that MyClass got defined only once, even though the header was included twice. And so the resulting code is valid.

This is an important property of header files. Always define your headers so that it is valid to include them multiple times.

jalf