Having a constant to be used across entire application. Use #define or variable [duplicate]
Possible Duplicate:
static const vs #define
Hello all, in C++, to define a constant to be used across the entire application, what i开发者_开发技巧s your guys usual practice?
#define WINDOWS_HEIGHT 1024
or
const int WINDOWS_HEIGHT = 1024;
Thanks.
How about using enum
and not to worry about linkage?
Pros and cons to everything, depending on usage:
- enums
- only possible for integer values
- properly scoped / identifier clash issues handled nicely
- strongly typed, but to a big-enough signed-or-unsigned int size over which you have no control (in C++03)
- can't take the address
- stronger usage restraints (e.g. incrementing -
template <typename T> void f(T t) { cout << ++t; }
won't compile) - each constant's type taken from the enclosing enum, so
template <typename T> void f(T)
get a distinct instantiation when passed the same numeric value from different enums, all of which are distinct from any actual f(int) instantiation. - even with typeof, can't expect numeric_limits to provide useful insight
- the enum's typename may appear in various places in RTTI, compiler messages etc. - possibly useful, possibly obfuscation
- consts
- properly scoped / identifier clash issues handled nicely
- strong, single, user-specified type
- One Definition Rule complications
- defines
- "global" scope / more prone to conflicting usages, which can produce hard-to-resolve compilation issues and unexpected run-time results rather than sane error messages; mitigating this requires:
- long, obscure and/or centrally coordinated identifiers, and access to them can't benefit from implicitly matching used/current/Koenig-looked-up namespace, namespace aliases etc.
- use of all uppercase characters is generally required and reserved for preprocessor defines (an important guideline for enterprise scale preprocessor usage to remain manageable, and which 3rd party libraries can be expected to follow), observation of which implies migration of existing consts or enums to defines involves a change in capitalisation (and hence affects client code). (Personally, I capitalise the first letter of enums but not consts, so I'd be hit here anyway - maybe time to rethink that.)
- more compile-time operations possible: string literal concatenation, stringification (taking size thereof)
- downside is that given
#define X "x"
and some client usage ala"pre" X "post"
, you're in trouble if you want or need to make X a runtime-changeable variable rather than a constant, whereas that transition is easier from aconst char*
orconst std::string
given they already force the user to incorporate concatenation operations.
- downside is that given
- can't use sizeof directly on a defined numeric constant
- untyped (GCC doesn't warn if compared to unsigned)
- some compiler/linker/debugger chains may not present the identifier, so you'll be reduced to looking at "magic numbers" (strings, whatever...)
- can't take the address
- the substituted value need not be legal (or discrete) in the context where the #define is created, as it's evaluated at each point of use, so you can reference not-yet-declared objects, depend on "implementation" that needn't be pre-included, create "constants" such as
{ 1, 2 }
that can be used to initialise arrays, or#define MICROSECONDS *1E-6
etc. (definitely not recommending this!) - some special things like
__FILE__
and__LINE__
can be incorporated into the macro substitution
- "global" scope / more prone to conflicting usages, which can produce hard-to-resolve compilation issues and unexpected run-time results rather than sane error messages; mitigating this requires:
As a general rule, I use consts and consider them the most professional option for general usage (though the others have a simplicity appealing to this old lazy programmer).
Hmm, depends. For integer constants enum
works great. Something like:
struct Constants {
enum {
WindowHeight = 8,
WindowWidth = 8,
// ...
};
};
...
int h = Constants::WindowHeight;
Use the constant integer; it will show up in the debugger where that #define value may not. Or use an enum; that works too.
my vote is for 'namespace scope extern const' variable defined in one ane only one translation unit. namespace scope 'const' variables have internal linkage.
I use namespace scope extern const.
using a define simply replaces all occurrences in your code with that value. A const global variable is nearly the same, only the type can be explicitly defined. This is pretty much the only difference.
Personally, I would prefer to use a define, just out of taste.
But, again, I don't think there is any difference.
精彩评论