Portfollio

Menu

Tricky C++: Making Things Constant

C++ is a confusing language that is difficult to write and in some ways even more difficult to read, especially if a developer doesn’t follow good programming practices. One way of writing better C++ code is to make use of the const keyword. Const enforces the policy of un-modifiability and can be used in conjunction with both variables and class methods.

Const Variables

A constant variable is a variable that cannot be altered, and must be initialised when declared because it cannot be changed later on! The following is an example of a const variable.

​The syntax for a constant variable is similar to that of any other variable, bar the introduction of the const keyword that is added before defining the type of the variable.

Note: A constant reference acts like a const variable except the address stored in a reference points to data that cannot be modified as opposed to storing the unmodified data itself.

Const Pointers

Any type in C++ can be defined as const, including pointers. In the case of a pointer the position of the const keyword has a different meaning. The code below shows different ways in which const is applied to a pointer.

The above example shows the three different ways in which const can be applied. Applying const anywhere before the ‘*’ states the data located at the memory address stored by the pointer must be constant. In this case the pointer has to point to data that is defined as constant.

Applying const after the ‘*’ states that the pointer itself is const, i.e. the address stored in the pointer cannot be altered, which also means the pointer must be initialised when declared.

Note: A pointer with a constant address can be compared to a reference, as a reference cannot alter the address it stores after it has been initialised.

Const to non -const

There is one final issue with regards to const that needs to be addressed, regarding the assignment of a const variable to a non const variable. A variable that is constant cannot be assigned to variable that isn’t defined as constant if the assignment copies the address of the value, and not the data itself.
​
Assigning data from one variable to another involves copying the data, and storing it in a new memory location. Because of this when the new variable modifies the data it is modifying its own copy and not the original data defined as constant, so the original data remains unchanged. Whereas passing the address of constant data to a variable that isn’t defined as constant would give that variable permission to modify the data, which was defined as unmodifiable. This would defeat the purpose of defining the original variable as constant.

Const Methods

Additional to variable constness, const can be applied at the end of a class method and will enforce that the object will not be altered in this function, i.e. the data members of the object cannot be changed. There are few rules regarding the use of const:

Const methods can be called by non const objects because defining a method as const simply states that member data won’t be changed. The object calling the data may still want to change its members in a different method.

Defining an instance of an object as const, and therefore unmodifiable, means that only const methods can be called by that object. Again if the object is defined as constant then calling non constant methods doesn’t make sense as these methods have the ability to alter the data of the object.

A constant function can only return a constant value.

​Note: const is included in a function signature which means two methods can be produced, one const, and one not dependent on the object calling the method.

Consts in Use

The use of const within C++ is a tool to make code easier to read, which in turn can help with maintainability. There are several different ways in which constant values can help achieve this.

The most common example of using const is to define a set of values as const which will be unchanged but used extensively through a program. If there is a case where the same value is used repeatedly throughout, it is better to establish that value as a constant and then use the variable throughout the code instead. The result of this is that fewer errors can be made because the value is being written only once, when the variable is initialised. Secondly if the const value does need to change this only needs to occur in one location. Finally, it is easier to read a program that contains constants, than simply values, because they are named, and because in some cases a programmer might use values that are not commonly known, and this can make it difficult to understand their purpose.

Note: consts variable names are usually made capital e.g. pi becomes PI, which makes it easier to identify these values within a program.

The use of constentness helps clarify the intended use of a variable or method. Defining a parameter or return type as constant means that the values being used in a function or returned by that function are not to be modified. A const method tells someone that this function was not created with the intention of altering the members of a class. Any lack of understanding that results in an attempt at altering a constant value will cause the compiler to complain, so a programmer has no way of mishandling the piece of code.

A final example is the use of const to help with encapsulation. To summarise, encapsulation refers to hiding data and methods from other classes and is used to ensure no unauthorised manipulation occurs to the class. A classes interface defines the behaviours the class carries out, and these behaviours establish how, if possible, the data a class stores can be manipulated. By not hiding data or certain methods in a class an outsider could cause issues such as assigning an unwanted value to a variable that could cause errors, for instance assigning a zero to a value that is used within a division.

The use of const can help enforce the concept of encapsulation, specifically when using Getter methods within a class. A value returned “by value” from a Getter does not break encapsulation as a copy of the data stored in the class is being manipulated and not the original. However, if an address is returned instead, then objects outside of the class have the ability to manipulate the data stored within the class, which does break encapsulation.

Summary

To summarise, this article has provided overview of the const keyword, how it can be applied to variables, and methods, as well as providing examples of how const can help create more readable C++ code.

using const on a variable means its data cannot be altered.

const pointers can mean the data cannot be altered, the address the pointer stores cannot change, or both.

A constant pointer or reference cannot be assigned to a non-constant value because that would allow the data stored at the address to be changed

Using const with class methods prevents that method from altering the data members of the class.

Const makes C++ code more readable and should be used as an alternative to literals if they are used extensively within a program and do not change.

Using const helps definition the intentions of a variable or method

Having constant return values within Getter methods helps enforce encapsulation by ensuring the returned value cannot be altered from outside the class.