include guards for large projects

Started by
6 comments, last by Hodgman 10 years, 6 months ago

does any of you have any tutorial for this?

I'm working on a very large project and every time i add a class i get 12157906125 compile errors.

every .h is guarded AND every #include is re-guarded and sometimes i have to use forward declaration but still I got problems....

Now I've been stuck half an hour since the last time i created the last file:


#ifndef __SPRITE_H__
#define __SPRITE_H__
#ifndef __OBJECT_H__
#include "Object.h"
#endif

class Sprite: public Object
{
/////CODE
};

#endif

i tried to play a little with the guard by removing them but nothing to do...

Error 29 error C2504: 'Object' : base class undefined c:\users\eltharynd\documents\visual studio 2012\projects\space\space\sprite.h 9 1 Space
please help me...
Advertisement

Forward declarations shouldn't be your last straw if nothing else helps, they should be your default whenever your header only uses pointers or references to something. You should always minimize the includes in header files, not only because of the mess you currently seem to find yourself in, but also because a huge web of includes will result in every source file being ridiculously huge and bloated after the preprocessor is done with it and make compilation take forever.

Also, since "include" is nothing but "copy/paste the file content right here", your double and triple checking is redundant, messy and in a best case scenario saves a few microseconds for the file access on any subsequent inclusion attempt.

You're drowning in a dependency mess and are flailing to stay above water. The solution isn't to learn how to swim, but to get out of the water. Object and sprite should be a very straight forward one-way dependency, so the question to ask is: why is object.h directly or indirectly including sprite.h? No amount of inclusions guards can fix circular includes.

f@dzhttp://festini.device-zero.de
I totally agree with Trienco except on one point: the extra inclusion guards not being worth it... That is incorrect in any large codebase unfortunately. The insertion style of the preprocessor costs a lot actually. Every included file must be both lexxed and parsed even if it is completely ignored. The reason being that I can have a header where each file which includes it changes preprocessor defines and as such the results of inclusion change from parse to parse. An include guard around the header unique define removes the overhead since "you" know, but the compiler does not, that nothing in the header parse will change. Most compilers now include a "pragma once" specifically for this reason, the compiler will assume nothing in the parse can change and as such if included once, it will not lexx/parse the file again if it see's the include.

A recent thread is a perfect example, in production code I had to do the following:


#include "Myheader.h"
#undef MEMORY_TRACKING
#include "MemoryTracking.h"
#include <vector>
#define MEMORY_TRACKING
#include "MemoryTracking.h"

.. my code..
With well documented headers, potentially lots of different preprocessor defines, such unprotected headers are a bane to multicore compilations. The file cache is usually smaller than your source code, as such, multiple cores end up fighting over disk access for no good reason except to repeatedly parse unchanging files.

pragma once is actually something I seem to have forgotten to mention. Unless one has to worry about obscure or outdated compilers, I'd always prefer that over the ifndef/define mess. Not just for potential optimizations, but because it's also less error prone in a copy/paste-happy environment (forget to update the include guard and figure out where all the weird errors are coming from).

f@dzhttp://festini.device-zero.de

This is especially true when your includes start looking like


#ifndef SOMEPROJNAME_SOMENAMESPACE_SOMEOTHERNAMESPACE_qzrt8Agk17L_H_
#define SOMEPROJNAME_SOMENAMESPACE_SOMEOTHERNAMESPACE_qzrt8Agk17L_H_

//stuff

#endif

Slightly exaggerated. ...Slightly.

Edit: On that note, OP, it's generally bad practice to prefix anything with an underscore, or have any double underscores at all in user-defined stuff.

As a side note.

Isn't pragma once pretty widespread nowadays?

Previously "Krohm"

According to Wikipedia it's fairly widespread. For normal situations relying just on #pragma once should be enough, although I'm not sure how things would look on consoles. I have no real interest nor experience in that area but at least in the past some of the (so-called) C++ compilers used there were very minimalistic.

In the past, consoles have had dodgey C++ compilers (as have most embedded devices), but these days they'd likely have just as much C++11 support as their desktop counterparts.

Despite this history, even the old ones still supported pragma once. I don't know of any compiler that doesnt tongue.png

This topic is closed to new replies.

Advertisement