CS 246: Software Abstraction and Specification Constants, References Readings: Eckel, Vol. 1 Ch. 8 Constants Ch. 11 References and the Copy Constructor U Waterloo CS246se (Spring 2011) p.1/14
Uses of const Value substitution (constant must be initialized in its definition) const int size = 256; char input[size]; Assertion that variable won't change value - pointers and const - const function arguments and return values - const in classes - static U Waterloo CS246se (Spring 2011) p.2/14
Scope of a Constant By default, a constant is visible only within the file where it is defined. - scope is smaller if defined inside a function or in a pair of scope braces To define a global constant, we must explicitly define it to be extern(ally) visible. - files that want to use a global constant must use extern declaration File A defines global constant extern const int size = 100; char input[size]; File B declares use of global constant extern const int size; for (int i=0; i<size; i++) {... } U Waterloo CS246se (Spring 2011) p.3/14
Pointers and Constants When the modifier const is applied in pointer definitions. Depending on where the const is placed, either the pointer is constant or its dereferenced variable is constant const int w = 25; const int *p3 = &w; int x = 5; int * const p4 = &x; // alternatively // int &p4 = x; const int z = 37; const int * const p5 = &z; p3 300 25 w p4 100 5 p5 308 37 dashed memory locations are constants x z U Waterloo CS246se (Spring 2011) p.4/14
Pointers and Constants What do the following declarations mean? const int* u; int const* v; int d = 1; int* const w = &d; const int* const x = &d; int const* const x2 = &d; Bruck Eckel, Thinking in C++ Vol. 1 U Waterloo CS246se (Spring 2011) p.5/14
Type Checking and Constants C++ type checking will not allow assignments of const objects to pointers to non-const referents. - because it would allow the const object to be changed via the pointer int d = 1; const int e = 2; int* u = &d; // OK -- d not const //! int* v = &e; // Illegal -- e const int* w = (int*)&e; // Legal but bad practice Bruck Eckel, Thinking in C++ Vol. 1 U Waterloo CS246se (Spring 2011) p.6/14
References A reference (&) is a constant alias for another object. Rational r(3,4); Rational &x = r; cout << "x = " << x << ", r = " << r << endl; x = x + 1; cout << "x = " << x << ", r = " << r << endl; 3 rules for using references: must be initialized when it is created cannot have NULL references once initialized, it cannot be changed to refer to another object U Waterloo CS246se (Spring 2011) p.7/14
References in Functions The most common usage of references is as function arguments and return values. istream& operator>> (istream &sin, Rational &r) { char slash; } sin >> r.numerator_ >> slash >> r.denominator_; return sin; A reference argument is an alias to the object passed in - any change to the reference changes the object outside the function A reference return value is an alias to the object returned. U Waterloo CS246se (Spring 2011) p.8/14
Constant Parameters The const parameter declaration is a guarantee that the routine does not modify the parameter. can apply the function to constants can apply the function to temporary objects (which are constants) void r( const int &i, const int &j, const Rational &r ) { //! i = 3; // compiler errors, arguments are read only! //! r = Rational(3,4); //! v[0] = 3; } // following call is legal r( 10, i + j, Rational(3,4) ); Best Practice: Whenever possible, pass parameters by const reference U Waterloo CS246se (Spring 2011) p.9/14
Constant Function Return Values We declare a function return to be const if we want to prevent the client programmer from modifying the result of a function call. const Rational operator+ (const Rational&, const Rational&){... } int main() { Rational r(1,2); Rational s(1,3); Rational t = r + s; // OK - value is copied to t // (r+s) = r; ERROR - cannot assign to const object } U Waterloo CS246se (Spring 2011) p.10/14
Constant Data Members A const data member is a constant associated with an object - every object may have a different value for constant class StrStack { public:... private: const int STACK_SIZE; string items_ [STACK_SIZE]; int top_; // top of stack }; Initialization is tricky - constant is initialized when its object is created (constructor) - must be initialized before body of constructor executes U Waterloo CS246se (Spring 2011) p.11/14
Constructor Initialization List class StrStack { public: StrStack (int size);... private: const int STACK_SIZE; string items_ [STACK_SIZE]; int top_; // top of stack }; // constructor StrStack::StrStack(int size) : STACK_SIZE(size), top_(-1) { } Syntax resembles "constructor calls" to data member's constructors Initialization occurs before constructor body executes U Waterloo CS246se (Spring 2011) p.12/14
Class Constants Alternatively, may want to define a constant that is associated with a class (and all of its objects) static const must be initialized when defined class StrStack { public:... private: static const int STACK_SIZE = 10; string items_ [STACK_SIZE]; int top_; // top of stack }; U Waterloo CS246se (Spring 2011) p.13/14
Constant Member Functions A constant member function is guaranteed not to change the function's object (*this). can apply the function to constant objects class Rational { public: int numerator() const; void numeratoris(const int);... }; // Accessor // Mutator const Rational s(2,3); cout << s.numerator() << endl; // OK //! s.numeratoris(5); // type error Best Practice: Whenever possible, use const member funcations. U Waterloo CS246se (Spring 2011) p.14/14