A. K.
A. K.

Reputation: 38136

Is it possible to write header file without include guard, and without multiple definition errors?

Just out of curiosity I wanted to know if is there a way to achieve this.

In C++ we learn that we should avoid using macros. But when we use include guards, we do use at least one macro. So I was wondering if there is a way to write a macro-free program.

Upvotes: 3

Views: 1790

Answers (5)

Carl
Carl

Reputation: 44448

In short, yes, even without pragmas. Only if you can guarantee that every header file is included only once. However, given how code tends to grow, it becomes increasingly difficult to honour that guarantee as the number of header files increase. This is why not using header guards is considered bad practice.

Pre-processor macros are frowned upon, yes. However, header include guards are a necessary evil because the alternative is so much worse (#pragma once will only work if your compiler supports it, so you lose portability)

With regard to pre-processor macros, use this rule: If you can come up with an elegant solution that does not involve a macro, then avoid them.

Upvotes: 1

Dietmar Kühl
Dietmar Kühl

Reputation: 153820

It is definitely doable and I have used some early C++ libraries which followed an already misguided approach from C which essentially required the user of a header to include certain other headers before this. This is based on thoroughly understanding what creates a dependency on what else and to use declarations rather than definitions wherever possible:

  • Declarations can be repeated multiple times although they are obviously required to be consistent and some entities can't be declared (e.g. enum can only be defined; in C++ 2011 it is possible to also declare enums).
  • Definitions can't be repeated but are only needed when the definition if really used. For example, using a pointer or a reference to a class doesn't need its definition but only its declaration.

The approach to writing headers would, thus, essentially consist of trying to avoid definitions as much as possible and only use declaration as far as possible: these can be repeated in a header file or corresponding headers can even be included multiple times. The primary need for definitions comes in when you need to derive from a base class: this can't be avoided and essentially means that the user would have to include the header for the base class before using any of the derived classes. The same is true for members defined directly in the class but using the pimpl-idiom the need for member definitions can be pushed to the implementation file.

Although there are a few advantages to this approach it also has a few severe drawbacks. The primary advantage is that it kind of enforces a very thorough separation and dependency management. On the other hand, overly aggressive separation e.g. using the pimpl-idiom for everything also has a negative performance impact. The biggest drawback is that a lot the implementation details are implicitly visible to the user of a header because the respective headers this one depends on need to be included first explicitly. At least, the compiler enforces that you get the order of include files right.

From a usability and dependency point of view I think there is a general consensus that headers are best self-contained and that the use of include guards is the lesser evil.

Upvotes: 1

eplawless
eplawless

Reputation: 4323

It's definitely possible, though it's unimaginably bad practice not to have include guards. It's important to understand what the #include statement actually does: the contents of another file are pasted directly into your source file before it's compiled. An include guard prevents the same code from being pasted again.

Including a file only causes an error if it would be incorrect to type the contents of that file at the position you included it. As an example, you can declare (note: declare, not define) the same function (or class) multiple times in a single compilation unit. If your header file consists only of declarations, you don't need to specify an include guard.

IncludedFile.h

class SomeClassSomewhere;
void SomeExternalFunction(int x, char y);

Main.cpp

#include "IncludedFile.h"
#include "IncludedFile.h"
#include "IncludedFile.h"

int main(int argc, char **argv)
{
    return 0;
}

While declaring a function (or class) multiple times is fine, it isn't okay to define the same function (or class) more than once. If there are two or more definitions for a function, the linker doesn't know which one to choose and gives up with a "multiply defined symbols" error.

In C++, it's very common for header files to include class definitions. An include guard prevents the #included file from being pasted into your source file a second time, which means your definitions will only appear once in the compiled code, and the linker won't be confused.

Rather than trying to figure out when you need to use them and when you don't, just always use include guards. Avoiding macros most of the time is a good idea; this is one situation where they aren't evil, and using them here isn't dangerous.

Upvotes: 3

Alok Save
Alok Save

Reputation: 206518

It is possible to do so if you ensure the same header file is not being included in the same translation unit multiple times.

Also, you could use:

#pragma once

if portability is not your concern.

However, you should avoid using #pragma once over Include Guards because:

  • It is not standard & hence non portable.
  • It is less intuitive and not all users might know of it.
  • It provides no big advantage over the classic and very well known Include Guards.

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 753675

Does the non-portable, non-standard

#pragma once

work sufficiently well for you? Personally, I'd rather use macros for preventing reinclusion, but that's your decision.

Upvotes: 0

Related Questions