The const Keyword Extreme Encapsulation
Humble Beginnings There are often cases in coding where it is helpful to use a const variable in a method or program. – Even when working with fixed values, it is best to abstract them with variable names. It’s more helpful (debugging-wise) to see “array_length” than tons of copies of the same number everywhere.
Humble Beginnings With object-orientation, many classes may take permanent values which are unique to each instance of the class, specified during initialization. – As these should not change at any point in the object’s lifetime, const makes sense.
Humble Beginnings The use of const is fairly straightforward for the primitive data types – the basic building blocks of the language. Things get more complicated when we use const with pointers and with objects.
const and Objects What would it mean for an object to be const ?
const and Objects What would it mean for an object to be const ? – If declared const, an object should not be modifiable. – Problem: how can we use its methods while being sure not to modify it?
const and Objects In C++, whenever a variable is declared const, no modifications are allowed to it, in a by-value manner. – As the compiler is not powerful enough to ensure that its methods do not modify it, by default C++ blocks all use of any class methods. This would be a huge problem for encapsulation.
const and Objects The C++ solution to the problem this poses: functions can be declared const. – Appending the const keyword to a function signifies that the method is not allowed to alter the class in any manner. – Inside that method, all fields of the class will be treated as if they were declared const.
const and Objects Let us now examine how this would look in code, through our frequent Person class example.
A First Object public class Person { private: const string name; int age; public: Person(string name, int age) string getName() const; int getAge() const; void haveABirthday(); }
A First Object string Person::getName() const { return this->name; } int Person::getAge() const { return this->age; }
A First Object public void haveABirthday() { this->age++; } Note: declaring this method as const would result in a compile-time error, as age would be treated as const within the method.
const and Objects Which of the following code lines is invalid? const Person p(“Joshua”, 28); string name = p.getName(); int age = p.getAge(); p.haveABirthday();
const and Objects Which of the following code lines is invalid? p.haveABirthday(); As this method is not declared const, a compile-time error would result from this method being called upon const p.
Exercise 1 Bust out your Person code and modify it to make const methods Modify your main() to declare a const person object Try to access the object with all methods Compile & run Fix
const and Pointers When we add pointers into the mix, things get even more interesting. – What might we wish to be constant? The stored address / pointer The referenced value
const and Pointers In order to have a const pointer to a changeable value, use the following syntax: – int* const myVariable ; To allow the stored address to be replaced, but have the referenced value be otherwise unchangeable: – const int* myVariable ;
const and Pointers Using the syntax below, while obj is declared by-reference, the compiler will block any attempts to modify its contents: – const Object* obj ; – The referenced object obj is considered constant.
const and Pointers The simplest way to think of it – read const definitions from right to left. – int* const myVariable ; – const int* myVariable ; When const is fully on the left, it modifies the direct right instead. int const* myVariable; – Is the same definition, with different ordering.
const and Pointers While very powerful, const syntax can get rather crazy: – const Object* const obj ; – Translation: const Object* const obj ; A const reference… const Object* const obj ; to a const Object.
const and Pointers Similar rules apply to arrays. – The following may store a constant reference to an array with changeable values: int* const myVariable ; – The following may store a replaceable reference to arrays whose values are treated as const : const int* myVariable ;
const and Pointers Example: int* initArray = new int[6]; int* const myVariable = initArray; myVariable = new int[3]; //Above: Not legal myVariable[2] = 3; // Legal! …
const and Pointers Example: int* initArray = new int[6]; const int* myVariable = initArray; myVariable = new int[3]; //Above: Legal, not initialized myVariable[2] = 3; //Illegal! …
Exercise 2 Code up the previous examples with four int arrays – Non-const – Const int* – Int* const – Const int* const Code main() to access each of the array types in each way Compile, observe, comment out code that compiler doesn’t like
const and Parameters Suppose a method is defined as follows: void someMethod(const Object* obj) What implications would this have?
const and Parameters void someMethod(const Object* obj) What implications would this have? – As obj is defined const Object*, we would get a pointer to an unmodifiable instance of Object. – What are we able to pass in as an argument to obj ?
const and Parameters void someMethod(const Object* obj) Which of these would be proper calls? – const Object obj(); someMethod(&obj); – Object* obj = new Object(); someMethod(obj);
const and Parameters void someMethod(const Object* obj) Which of these would be proper calls? – const Object obj(); someMethod(&obj); – Object* obj = new Object(); someMethod(obj); Trick Question! Both!
const and Parameters void someMethod(const Object* obj) While the original argument to methods of this form do not have to be const, they become const within the method.
const and Parameters void someMethod(Object* obj) Which of these would be proper calls? – const Object obj(); someMethod(&obj); – Object* obj = new Object(); someMethod(obj);
const and Parameters void someMethod(Object* obj) Which of these would be proper calls? – const Object obj(); someMethod(&obj); – Object* obj = new Object(); someMethod(obj);
const and Parameters const objects cannot be passed by- reference to non- const function parameters. – As there is no guarantee that the referenced object will not be modified when passed to a non- const parameter, the compiler blocks this. – For value types, since a separate value is created, that separate copy is safe for the called function to edit.
const and Parameters const objects cannot be passed by- reference to non- const function parameters. – An interesting consequence of this: void someMethod(string &str); someMethod(string(“Hello World”)); // Will be a compile-time error // due to the compile-time constant.
const and Parameters const objects cannot be passed by- reference to non- const function parameters. – An interesting consequence of this: void someMethod(const string &str); someMethod(string(“Hello World”)); // Will work without issue!
const and Parameters A signature of the latter type – void someMethod(const string &str) has one additional benefit. – Since str is passed by reference here, the system doesn’t have to copy its value… – And since str is declared const, its value cannot be changed.
const and Parameters A signature of the latter type – void someMethod(const string &str) has one additional benefit. – Consider if this were a very large string. Or, just some very large object. – This makes the program more efficient in terms of run-time and in terms of memory use.
const and Return Values const may also be applied to return values! – Consider if we were to return a reference to an object’s internal field. – Rather than copy the internal object, we may wish to return it while blocking write access within the object. Example: const Object* gimmeObject();
const and Return Values While not mentioned thus far in class, this also affects the other return-by-reference type… const Object& gimmeObject(); This form, if not const, allows code to both modify that object and assign directly to its original variable!
Exercise 3 Code const and non-const parameter methods for some object Try passing const and non-const instances into the methods Compile and observe
const Design const allows the programmer to share values freely with other parts of the program while making them write-only. – This can be very useful for encapsulation! Return an array/internal reference “const type*” – the same array is used, but edits are prohibited!