Use const Instead of #define to Define Constants

Symbolic constants make code more readable and maintainable. The constant’s name indicates its meaning, and if you need to change the value, you just have to change the value once, in the definition, and then recompile. C uses the preprocessor to create symbolic names for a constant:

#define MAX_LENGTH 100

The preprocessor then does a text substitution in your source code, replacing occurrences of MAX_LENGTH with 100 prior to compilation.

The C++ approach is to apply the const modifier to a variable declaration:

const int MAX_LENGTH = 100;

This treats MAX_LENGTH as a read-only int.

There are several advantages to using the const approach. First, the declaration explicitly names the type. With #define, you must use various suffixes to a number to indicate types other than char, int, or double; for example, you use 100L to indicate a long type and 3.14F to indicate a float type. More importantly, the const approach can just as easily be used with compound types, as in this example:

const int base_vals[5] = {1000, 2000, 3500, 6000, 10000};
const string ans[3] = {"yes", "no", "maybe"};

Finally, const identifiers obey the same scope rules as variables. Thus, you can create constants with global scope, named namespace scope, and block scope. If, say, you define a constant in a particular function, you don’t have to worry about the definition conflicting with a global constant used elsewhere in a program. For example, consider the following:

#define n 5
const int dz = 12;
...
void fizzle()
{
    int n;
    int dz;
    ...
}

The preprocessor will replace

int n;

with

int 5;

and induce a compilation error. The dz defined in fizzle(), however, will be a local variable. Also if necessary, fizzle() can use the scope-resolution operator (::) and access the constant as ::dz.

C++ has borrowed the const keyword from C, but the C++ version is more useful. For example, the C++ version has internal linkage for external const values rather than the default external linkage used by variables and by the C const. This means that each file in a program using a const needs that const defined in that particular file. This might sound like extra work, but, in fact, it makes life easier. With internal linkage, you can place const definitions in a header file used by various files in a project. That is a compiler error for external linkage but not for internal linkage. Also because a const must be defined in the file that uses it (being in a header file used by that file satisfies the requirement), you can use const values as array size arguments:

const int MAX_LENGTH = 100;
...
double loads[MAX_LENGTH];
for (int i = 0; i < MAX_LENGTH; i++)
    loads[i] = 50;

This won’t work in C because the defining declaration for MAX_LENGTH could be in a separate file and not be available when this particular file is compiled. In fairness, it should be added that, in C, you could use the static modifier to create constants with internal linkage. It’s just that C++, by making static the default, requires one fewer thing for you to remember.

Incidentally, the revised C Standard (C99) allows you to use a const as an array size specification, but the array is treated as a new form of array, called a variable array, that is not part of the C++ Standard.

One role for the #define directive is still quite useful—the standard idiom for controlling when a header file is compiled:

// blooper.h
#ifndef _BLOOPER_H_
#define _BLOOPER_H_
// code goes here
#endif

For typical symbolic constants, however, you should get into the habit of using const instead of #define. Another good alternative, particularly when you have a set of related integer constants, is to use enum:

enum {LEVEL1 = 1, LEVEL2 = 2, LEVEL3 = 4, LEVEL4 = 8};

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.162.49