The const Keyword Extreme Encapsulation Humble Beginnings There
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 get. Name() const; int get. Age() const; void have. ABirthday(); }
A First Object string Person: : get. Name() const { return this->name; } int Person: : get. Age() const { return this->age; }
A First Object public void have. ABirthday() { 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. get. Name(); int age = p. get. Age(); p. have. ABirthday();
const and Objects • Which of the following code lines is invalid? p. have. ABirthday(); • 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 my. Variable; • To allow the stored address to be replaced, but have the referenced value be otherwise unchangeable: – const int* my. Variable;
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 my. Variable; – const int* my. Variable; • When const is fully on the left, it modifies the direct right instead. • int const* my. Variable; – 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 my. Variable; – The following may store a replaceable reference to arrays whose values are treated as const: • const int* my. Variable;
const and Pointers • Example: int* init. Array = new int[6]; int* const my. Variable = init. Array; my. Variable = new int[3]; //Above: Not legal my. Variable[2] = 3; // Legal! …
const and Pointers • Example: int* init. Array = new int[6]; const int* my. Variable = init. Array; my. Variable = new int[3]; //Above: Legal, not initialized my. Variable[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 some. Method(const Object* obj) • What implications would this have?
const and Parameters void some. Method(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 some. Method(const Object* obj) • Which of these would be proper calls? – const Object obj(); some. Method(&obj); – Object* obj = new Object(); some. Method(obj);
const and Parameters void some. Method(const Object* obj) • Which of these would be proper calls? – const Object obj(); some. Method(&obj); Trick Question! Both! – Object* obj = new Object(); some. Method(obj);
const and Parameters void some. Method(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 some. Method(Object* obj) • Which of these would be proper calls? – const Object obj(); some. Method(&obj); – Object* obj = new Object(); some. Method(obj);
const and Parameters void some. Method(Object* obj) • Which of these would be proper calls? – const Object obj(); some. Method(&obj); – Object* obj = new Object(); some. Method(obj);
const and Parameters • const objects cannot be passed byreference 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 byreference to non-const function parameters. – An interesting consequence of this: void some. Method(string &str); some. Method(string(“Hello World”)); // Will be a compile-time error // due to the compile-time constant.
const and Parameters • const objects cannot be passed byreference to non-const function parameters. – An interesting consequence of this: void some. Method(const string &str); some. Method(string(“Hello World”)); // Will work without issue!
const and Parameters • A signature of the latter type – void some. Method(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 some. Method(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* gimme. Object();
const and Return Values • While not mentioned thus far in class, this also affects the other return-by-reference type… const Object& gimme. Object(); • 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!
- Slides: 40