Constants in header files

Started by
18 comments, last by jflanglois 16 years, 11 months ago
Is this the correct way to declare some constants in a Cpp header file? Constants.h

#ifndef CONSTANTS_H
#define CONSTANTS_H

#include <string>

namespace myNamespace
{
    // this won't compile without the 'static'
    static const char* FOO_BAR = "foobar";

    // this will compile with or without the static
    static const std::string BETTER_STRING = "foobar2";

    // as will this
    static const float MAX_FUN = 1.5f;

    static const int GAME_ID = 2;

    enum { SHIP_ID = 3 };
};

#endif // CONSTANTS_H


Sorry if this is a stupid question but I was under the impression that if you do this wrong you end up declearing a copy of a constant for every file that includes the header.
Advertisement
If they are static and const, it doesn't matter much.
You have your defines in the top so that should prevent multiple inclusion.
And also what Deyja said.

I usually only use const, when defining global constants. Do not really know, why you can not define yours as so.
regards/thallishI don't care if I'm known, I'd rather people know me
I believe the "static" is what preventing the compiler to create multiple instances of the same data.

For my constants I use the #define directive.
for ex.

#define FOO_BAR = "foobar";
#define BETTER_STRING = "foobar2";
#define MAX_FUN = 1.5f;
#define GAME_ID = 2;

BTW,
There is not such thing as a stupid question. Ask as you wish. This is what the forum is for.
There is nothing that can't be solved. Just people that can't solve it. :)
Quote:Original post by DesignerX
I believe the "static" is what preventing the compiler to create multiple instances of the same data.

For my constants I use the #define directive.
for ex.

#define FOO_BAR = "foobar";
#define BETTER_STRING = "foobar2";
#define MAX_FUN = 1.5f;
#define GAME_ID = 2;

BTW,
There is not such thing as a stupid question. Ask as you wish. This is what the forum is for.


There is, unfortunately, such a thing as a bad answer. And unfortunately, the people giving them only have the best of intentions.

#defines are not to be used, unless you're using C, in which case they're your only option (and since you're not, don't). The evilness of defines are such that C++ introduced constants to take their place. The only time you should ever use defines is when you require conditional compilation (i.e. setting which operating system to compile on).

As for the problem with the const and the char*, with pointers you read right-to-left. So, as opposed to all the other declarations, where you're declaring the variable const, you're actually only declaring what you're pointing at ("foobar") to be const, and not the actual pointer itself (FOO_BAR). To do so, you want: const char * const FOO_BAR = "foobar";

That should work.
[ search: google ][ programming: msdn | boost | opengl ][ languages: nihongo ]
Quote:Original post by _goat
Quote:Original post by DesignerX
I believe the "static" is what preventing the compiler to create multiple instances of the same data.

For my constants I use the #define directive.
for ex.

#define FOO_BAR = "foobar";
#define BETTER_STRING = "foobar2";
#define MAX_FUN = 1.5f;
#define GAME_ID = 2;

BTW,
There is not such thing as a stupid question. Ask as you wish. This is what the forum is for.


There is, unfortunately, such a thing as a bad answer. And unfortunately, the people giving them only have the best of intentions.

#defines are not to be used, unless you're using C, in which case they're your only option (and since you're not, don't). The evilness of defines are such that C++ introduced constants to take their place. The only time you should ever use defines is when you require conditional compilation (i.e. setting which operating system to compile on).


I think you're verging into religious territory here; #defines are often used for defining constants with no ill effects. Oh sure there are theoretical problems but not so much real-world, if you're careful.

I do, however, agree with you about bad answers. "static" in fact tells the compiler the opposite of what you're saying, when used in a header file. "static" means that the symbol should be evaluated only within the context of the source file it is compiled into, and correctly used is handy for avoiding symbol conflicts. It almost does the opposite of what DesignerX suggests, as it instructs the compiler to keep a separate copy for each source file. However, in conjunction with const the compiler is smart enough to do the right thing.

Also #define doesn't use an "=" sign, and using one will may well create code that actually compiles but doesn't do at all what you expect, as the pre-processor will insert the "=" along with the constant that you're trying to define. Kind of making _goat's point.

Lastly, it's often a good idea to declare the constant in the header file, but put the actual value in a .cpp file. If you put the constant value in the header file, changing the value will require a recompile of every .cpp file that includes that header file.

Geoff
Quote:Original post by gdunbar
I think you're verging into religious territory here; #defines are often used for defining constants with no ill effects. Oh sure there are theoretical problems but not so much real-world, if you're careful.


But that's just the thing, why would you use something that requires you to be careful when the alternatives are just as easy and less prone to strange errors.
Lots of misleading answers here. As gdunbar says, defining a static variable in this context effectively leads to it being duplicated for every compilation unit (usually corresponding to every .cpp file). With static const variables this may be harmless - in the case of a float or an int the compiler will usually treat it as a literal and it will not necessarily be placed in memory at all - but in some cases with more complex types it may result in multiple copies of a value in your executable.

In a namespace scope variable definition, static says that the variable will have internal linkage. This prevents multiple definition errors from the linker (because the variable is not visible outside the compilation unit) but means that storage is allocated for the variable in every compilation unit that includes the header with the definition. Using const on the other hand just says that the variable cannot be modified. The variable will still default to external linkage and so you will get multiple definition errors from the linker if the definition appears in a header included by more than one compilation unit. One way round this is to put the declaration in the header and the definition (assigning a value) in the corresponding .cpp file. This way storage will only be allocated once for the variable but the downside is that you will probably lose the performance benefits of the compiler being able to make optimizations based on treating the constant as a literal.

The rules are different for static const variables declared at class scope. A static const integral member of a class can be defined in a header file and will behave as you'd expect. This doesn't work for other types like floating point types though - those have to be declared in the header and defined in a .cpp.

For numeric values using static const values defined in a header is probably fine in most cases. For anything else use a const value declared in the header and defined in the corresponding .cpp.

Game Programming Blog: www.mattnewport.com/blog

I usually declare it in the header but define it in the cpp to reduce dependencies, that way I can change the constant value without having to recompile everything that depends on the header, only recompile the cpp
Sorry gdunbar but I agree with jflanglois, I can't think of many advantages of using #defines for defining constants when it's just as easy to use c++ constants which have all the saftey of the c++ type system rather than just a glorified 'find and replace all' before each compile which is pretty much what a #define constant is.

Sounds like the moral of the story is that I should stick with what I originally had as suggested by ldeej and others which was something along the lines of this.

Constants.h
#ifndef CONSTANTS_H#define CONSTANTS_Hnamespace myNamespace{   struct Vec   {      float x,y,z;   };    extern const char*   NAME;   extern const int     VERSION;   extern const float   SHIP_SIZE;   extern const Vec     UP_VEC;}#endif CONSTANTS_H


Constants.cpp
#include "Constants.h"const char*   myNamespace::NAME          = "Decoda";const int     myNamespace::VERSION       = 2;const float   myNamespace::SHIP_SIZE     = 1.03f;const Vec     myNamespace::UP_VEC        = {0.0f,1.0f,0.0f};


On a related note for some reason I find the use of ALL_UPPERCASE for constants a bit old school. I notice that the Maya API uses a k prefix for all it's constants which I like the look of but at the same times seems a little odd as constant doesn't start with a k

eg. const float kShipSize = 2.0f;

What are peoples thoughts on constant naming conventions?

This topic is closed to new replies.

Advertisement