I have been running into a problem in my code lately. I have a file called "Constants.h" and one called "Constants.cpp." I define all my constants there. However, when I include Constants.h in another .h file I always get compile errors when, for example, trying to allocate arrays of a GIVEN_CONSTANT size. Is there a reason for this? I never get these errors in .cpp files. It seems like the pre-processor is not expanding my #includes into the header, or maybe there is a rule that constants can't be used in headers in c++? Can someone shed some light on this situation for me?

First of all, in your Constants.cpp file you need to write "const int MAX_INTS = 1000; "
The extern keyword means "declare without defining". In other words, it is a way to explicitly declare a variable, or to force a declaration without a definition.

The practice itself (putting the initialization into the cpp file) is a matter of personal taste. I personally like it because if i need to change the value for whatever reason, not every single file which includes the header file is compiled again.

But i wouldnt use "extern" anymore....i like static const uint32 MAX_INTS; in a header file more. ;-)

That will of course solve the problem, but for the OP's benefit I think it might be worth giving a little more background on why 'extern' isn't needed here.

For example, you can't put "int MAX_INTS = 1000;" in a header file without opening yourself up to ODR violations, despite the trivial visual differences between this definitions and "const int MAX_INTS = 1000;".

Muddying the waters further are differences in semantics between C and C++.

In C++, a definition such as "const int MAX_INTS = 1000;" defines the MAX_INT object with internal linkage. This means that if the definition resides within a header, and that header is #included in to multiple translation units, you're really creating a number of distinct objects (though I think a linker could still put them all at the same location in the end, as a space optimization).

However, "int MAX_INTS = 1000;" defines an object with external linkage because MAX_INTS is not const. This means that if this definition resides within a header, and that header is #included in to multiple translation units, you're defining a single object multiple times. This is an ODR (one definition rule) violation, which says (approximately) that objects with external linkage must have a single definition across the entire program. So in this case, the correct thing to do is indeed to declare MAX_INTS with 'extern' in a header, and then define it in a single translation unit.

In C, everything we've seen so far has external linkage. If you want to put a constant in a header, you either use a #define instead, or put 'static' in front of the definition to give each copy of the variable internal linkage within their respective translation units. You can also use 'static' in the C++ definitions too without causing harm, except for the redundant keyword.

There are some other rules too, making the whole subject quite intricate. But the important things to understand are the concepts of internal and external linkage. Knowledge about how and when definitions and declarations affect linkage will come with time and practice.

You really got the wrong conclusion from this. You don't know if using a const variable wastes any memory, so that's a terrible reason to pick one over the other. An optimized build with g++ generates identical code for both.

A const variable behaves like any other variable, while a macro constant has surprises: you can't take its address, it doesn't have a namespace, it doesn't obey the usual scoping rules, you can't access its value from a debugger, it can't be an object of a class...

You should write your code to be as clear as possible, minimizing surprises, not whether you might save 4 bytes (which you won't anyway). And therefore you should prefer using const variables over macros to represent constants.

Thank you for that additional input. Could you possibly link or attach an example of a (if possible complex) header defining const variables that use the features you list above such as namespaces, being objects in classes, having their addresses taken, etc. I guess I need to see what kind of complexity doing this entails, and if I will ever use those features.

Good examples of the namespacing problem come directly from Microsoft's <windows.h> header itself.

I bet many people here have hit the problem of trying to std::numeric_limits<int>::max(), or std::max(a, b) after #include-ing <windows.h>, only have the compiler to spit a weird error at them. This is because <windows.h> uses the preprocessor to define 'min' and 'max' macros.

This won't compile without additional hacks. This is because <windows.h> uses the preprocessor to define "DeleteFile" as either "DeleteFileA" or "DeleteFileW", depending on whether or not you've defined UNICODE. I've even gone to the care of putting my DeleteFile in its own namespace. But it doesn't make a difference to the preprocessor.

Not only does the preprocessor not respect C++ namespaces, but there's no way of putting macros themselves in to any kind of namespace, meaning that everyone has to (or really should) add a prefix to the front of their macros.

So <windows.h> is a horrible header. I could list a number of other real-world examples where it has damaged perfectly reasonable code. I actually have a policy to never include it in a public header because of the carnage it can cause. I would not recommend using it for inspiration!

Though sometimes useful, the preprocessor should be avoided where possible, especially if there's an alternative, which in this case there is. Use "const int MAX_INTS = 1000;" instead. You really shouldn't be worrying about wasting 4 bytes here or there.

The code in the header file would look exactly as I posted above, except for possibly being in a namespace. But if you aren't using namespaces [yet], there is no point in putting this particular thing in a namespace.

I can't post any code from work, but we do this type of thing all the time there.

Just test to print the value of the constant from a debugger, and you'll immediately see one of the benefits of using a const variable.

Keep in mind that the MS windows headers are designed to be used from C as well as C++. So while there are (reasonably) good reasons for what they do in their code, you should only copy them if you are working under the same kind of constraint.

Also, for integral constants, another option is using an enum. Like a #define it never occupies storage, but like const variables it respects scope.

If I have a const string I access from several places, should I declare it extern and move definition to a .cpp or make it static? Since just making it const string in the header would create multiple objects?

Unless your constants have some sort of logical reason that they should be either grouped together or sectioned off from other symbols, then there's no point in creating a namespace just for constants. For example, you might group constants that form flags together or constants for private use separate from other symbols. But there's no point to dumping all your constants in a namespace just to have a namespace.