400 likes | 536 Views
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.
E N D
The constKeyword Extreme Encapsulation
Humble Beginnings • There are often cases in coding where it is helpful to use a constvariable 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, constmakes 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.
constand Objects • What would it mean for an object to be const?
constand 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?
constand 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.
constand 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, allfields of the class will be treated as if they were declared const.
constand Objects • Let us now examine how this would look in code, through our frequent Person class example.
A First Object public class Person { private: conststringname; intage; public: Person(stringname, intage) stringgetName() const; intgetAge() const; voidhaveABirthday(); }
A First Object string Person::getName() const { returnthis->name; } intPerson::getAge() const { returnthis->age; }
A First Object public void haveABirthday() { this->age++; } • Note: declaring this method as constwould result in a compile-time error, as age would be treated as const within the method.
constand Objects • Which of the following code lines is invalid? const Person p(“Joshua”, 28); string name = p.getName(); int age = p.getAge(); p.haveABirthday();
constand 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
constand 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
constand Pointers • In order to have a constpointer to a changeable value, use the following syntax: • int* constmyVariable; • To allow the stored address to be replaced, but have the referenced value be otherwise unchangeable: • constint* myVariable;
constand Pointers • Using the syntax below, while objis declared by-reference, the compiler will block any attempts to modify its contents: • constObject* obj; • The referenced object obj is considered constant.
constand Pointers • The simplest way to think of it – read constdefinitions from right to left. • int* constmyVariable; • constint* myVariable; • When constis fully on the left, it modifies the direct right instead. • intconst* myVariable; • Is the same definition, with different ordering.
constand Pointers • While very powerful, const syntax can get rather crazy: • constObject* constobj; • Translation: • constObject* constobj; • A const reference… • constObject*constobj; • to a const Object.
constand Pointers • Similar rules apply to arrays. • The following may store a constant reference to an array with changeable values: • int* constmyVariable; • The following may store a replaceable reference to arrays whose values are treated as const: • constint* myVariable;
constand Pointers • Example: int* initArray = newint[6]; int* constmyVariable = initArray; myVariable = newint[3]; //Above: Not legal myVariable[2] = 3; // Legal! …
constand Pointers • Example: int* initArray = newint[6]; constint* myVariable = initArray; myVariable = newint[3]; //Above: Legal, not initialized myVariable[2] = 3;//Illegal! …
Exercise 2 • Code up the previous examples with four int arrays • Non-const • Constint* • Int* const • Constint* const • Code main() to access each of the array types in each way • Compile, observe, comment out code that compiler doesn’t like
constand Parameters • Suppose a method is defined as follows: voidsomeMethod(const Object* obj) • What implications would this have?
constand Parameters voidsomeMethod(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?
constand Parameters voidsomeMethod(const Object* obj) • Which of these would be proper calls? • const Object obj();someMethod(&obj); • Object* obj = new Object();someMethod(obj);
constand Parameters voidsomeMethod(const Object* obj) • Which of these would be proper calls? • const Object obj();someMethod(&obj); • Object* obj = new Object();someMethod(obj); Trick Question! Both!
constand Parameters voidsomeMethod(const Object* obj) • While the original argument to methods of this form do not have to be const, they become const within the method.
constand Parameters voidsomeMethod(Object* obj) • Which of these would be proper calls? • const Object obj();someMethod(&obj); • Object* obj = new Object();someMethod(obj);
constand Parameters voidsomeMethod(Object* obj) • Which of these would be proper calls? • const Object obj();someMethod(&obj); • Object* obj = new Object();someMethod(obj);
constand Parameters • constobjects 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.
constand Parameters • constobjects cannot be passed by-reference to non-const function parameters. • An interesting consequence of this: voidsomeMethod(string &str); someMethod(string(“Hello World”)); // Will be a compile-time error // due to the compile-time constant.
constand Parameters • constobjects cannot be passed by-reference to non-const function parameters. • An interesting consequence of this: voidsomeMethod(conststring &str); someMethod(string(“Hello World”)); // Will work without issue!
constand Parameters • A signature of the latter type –voidsomeMethod(conststring &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.
constand Parameters • A signature of the latter type –voidsomeMethod(conststring &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.
constand Return Values • constmay 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();
constand Return Values • While not mentioned thus far in class, this also affects the other return-by-reference type… constObject& 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
constDesign • constallows 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 “consttype*” – the same array is used, but edits are prohibited!