Define constant variables in C++ header
You could simply define a series of const ints
in a header file:
// Constants.h
#if !defined(MYLIB_CONSTANTS_H)
#define MYLIB_CONSTANTS_H 1
const int a = 100;
const int b = 0x7f;
#endif
This works because in C++ a name at namespace scope (including the global namespace) that is explicitly declared const and not explicitly declared extern has internal linkage, so these variables would not cause duplicate symbols when you link together translation units. Alternatively you could explicitly declare the constants as static.
static const int a = 100;
static const int b = 0x7f;
This is more compatible with C and more readable for people that may not be familiar with C++ linkage rules.
If all the constants are ints then another method you could use is to declare the identifiers as enums.
enum mylib_constants {
a = 100;
b = 0x7f;
};
All of these methods use only a header and allow the declared names to be used as compile time constants. Using extern const int
and a separate implementation file prevents the names from being used as compile time constants.
Note that the rule that makes certain constants implicitly internal linkage does apply to pointers, exactly like constants of other types. The tricky thing though is that marking a pointer as const
requires syntax a little different that most people use to make variables of other types const. You need to do:
int * const ptr;
to make a constant pointer, so that the rule will apply to it.
Also note that this is one reason I prefer to consistently put const
after the type: int const
instead of const int
. I also put the *
next to the variable: i.e. int *ptr;
instead of int* ptr;
(compare also this discussion).
I like to do these sorts of things because they reflect the general case of how C++ really works. The alternatives (const int
, int* p
) are just special cased to make some simple things more readable. The problem is that when you step out of those simple cases, the special cased alternatives become actively misleading.
So although the earlier examples show the common usage of const
, I would actually recommend people write them like this:
int const a = 100;
int const b = 0x7f;
and
static int const a = 100;
static int const b = 0x7f;
I like the namespace better for this kind of purpose.
Option 1 :
#ifndef MYLIB_CONSTANTS_H
#define MYLIB_CONSTANTS_H
// File Name : LibConstants.hpp Purpose : Global Constants for Lib Utils
namespace LibConstants
{
const int CurlTimeOut = 0xFF; // Just some example
...
}
#endif
// source.cpp
#include <LibConstants.hpp>
int value = LibConstants::CurlTimeOut;
Option 2 :
#ifndef MYLIB_CONSTANTS_H
#define MYLIB_CONSTANTS_H
// File Name : LibConstants.hpp Purpose : Global Constants for Lib Utils
namespace CurlConstants
{
const int CurlTimeOut = 0xFF; // Just some example
...
}
namespace MySQLConstants
{
const int DBPoolSize = 0xFF; // Just some example
...
}
#endif
// source.cpp
#include <LibConstants.hpp>
int value = CurlConstants::CurlTimeOut;
int val2 = MySQLConstants::DBPoolSize;
And I would never use a Class to hold this type of HardCoded Const variables.