# Define global constants

A note scribed by Jude Gao from book Effective C++.

Suppose we want to define a global constant such as LIMIT = 1000.

Don't use preprocessor macro to define global constants

It is a bad practice to use the preprocessor macro to define this global constant, namely, #define LIMIT 1000.

That is because the name LIMIT may not get entered into the symbol table. This can be confusing if you get an error during compilation involving the use of the constant, because the error message may refer to 1000, not LIMIT, particularly when LIMIT was defined in a header file you did not write.

Use a global constant instead

Define a constant as such const int 1000. It is perfectly fine with this approach. However, when you define a constant variable that is of pointer type. The variable needs to be both low-level as well as high-level constant.

Low-level constant concerns the underlying object pointed by the pointer variable, where as High-level constant concerns the pointer variable.

Hence, if we want to define a global constant pointer to an int, it is insufficient to just define it as const int *LIMIT = &value;, in which case LIMIT is not high-level constant. We must remember to define it as constant in both senses:

xxxxxxxxxxconst int * const LIMIT = &value;

How to define a class-specific constants

Since we do not want to have a copy of the constant for each instance of the class, we would like to make the constant static like this:

xxxxxxxxxxclass MyClass {    static const int LIMIT = 1000;};

Note that static const int LIMIT = 1000; is just a declaration, not a definition, so we must provide its definition elsewhere. That is commonly placed inside the .cpp implementation file. What this is saying is we should add the following line to our code to make our program compilable:

xxxxxxxxxxconst int MyClass::LIMIT;

Notice how we do not put static in the definition. Even though this constant does not seem to have been initialized, its initial value is provided in the declaration.

In contrast to non-constant static variable of a class, we cannot provide any in-class initializer to a static member, so this is compilable:

xxxxxxxxxxclass MyClass {    static int limit = 1000;};

In order to make it work, we first remove the in-class initializer, i.e. =1000, and provide a similar definition as in the constant case like int MyClass::LIMIT = 1000; Since this is a constant, you may leave it as uninitialized as such int MyClass::LIMIT;

enum hack We can define a class-specific constant by defining an enum, not an enum class, in the class. Here is an example:

xxxxxxxxxxclass Developer {    enum { WORK_HOURS_PER_WEEK = 40 };};

We can refer to our "constant" inside just by WORK_HOURS_PER_WEEK like we would do normally.

Put altogether In the following is a comprehensive example that illustrates these different complications as one defines a class-specific constant or non-constant variables.

xxxxxxxxxxclass Developer {    static const int base_salary = 100; // only a declaration, not a definition    static int current_interest; // non-const static method can not be initialized in-class    static const int head_count; // const static method may be initialized out of class as well    enum { WORK_HOURS_PER_WEEK = 40 }; // "enum hack"};​const int Developer::base_salary; // no static in frontint Developer::current_interest = 10;const int Developer::head_count = 30;