the second const used for cprogr

Upload: arief-rahman-hakim

Post on 07-Apr-2018

219 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/3/2019 The Second Const Used for CProgr

    1/6

    The purpose of the const keyword is to prevent accidental orunintentional change of a value.

    Let us examine some examples of using the const keyword and the typesof errors that will be generated, if we try to circumvent theprotection offered by the const keyword. Note that all error messagesdisplayed were generated by MS Visual Studio .NET 2003.

    Example 1:

    const int x = 10; // const protects x from being modified.// x must be initialized, or a compile error// will be generated.x = 5; // This is NOT allowed. Compiler error generated follows below.

    error C2166: l-value specifies const object

    Example 2:

    // Note that this function does not actually modify yvoid func(int & y){return;}

    int main(){const int x = 10; // const protects x from being// modified.func(x); // This is NOT allowed.}

    error C2664: 'func' : cannot convert parameter 1 from 'const int' to'int &'

    This error is generated because func() is not "promising" to notchange x's value. It does not matter that the function does notactually change x's value.

    If the function prototype was instead:

    void func( const int & y); // orvoid func( int const & y); // the order of const and int does not

    // matter

    there would be no compile error. Now the function is promising to notchange x's value through the use of the const keyword.

    This is another reason why we should attempt to make parameters of afunction const, so that the function can accept both const and non-const arguments.

    If the function prototype was instead:

    void func( int y);

    there would also be no compile error. Why? Because now y is beingpassed call by value, rather than call by reference, so we don't careif the function changes the argument.

  • 8/3/2019 The Second Const Used for CProgr

    2/6

    Example 3:

    int x = 10;int y = 20;const int *xPtr; // may NOT use pointer to modify value, but may// let pointer point to another address

    xPtr = & x; // this is allowedxPtr = & y; // and this is allowed as well

    *xPtr = 50; // This is NOT allowed. Attempting to dereference// the pointer and change the value at that address.

    error C2166: l-value specifies const object

    Example 4:

    int x = 10;int y = 20;int * const xPtr = &x; // may use pointer to modify value, but// may NOT let pointer point to another address

    xPtr = & y; // This is NOT allowed.

    *xPtr = 50; // But this is allowed.

    error C2166: l-value specifies const object

    Notice that in this example, xPtr must be initialized when it isdeclared, while in the previous example it was not necessary to do so.

    Example 5:

    int x = 10;int y = 20;const int * const xPtr = &x; // may NOT use pointer to modify// value, and may NOT let pointer point to another address

    xPtr = &y; // This is NOT allowed

    *xPtr = 50; // This is NOT allowed either

    error C2166: l-value specifies const objecterror C2166: l-value specifies const object

    This last example is simply Example 3 & 4 combined.

    Note that in the following function prototype, zPtr is being offeredthe exact same protection as xPtr in the above example.

    void func( const int * const zPtr);

    Do you think the xPtr from above could be passed to a function withthe following prototype?

    void func(const int * iPtr);

    Yes it can! Surprised? It is because, similar to what was discussed in

  • 8/3/2019 The Second Const Used for CProgr

    3/6

    Example 2 above, iPtr is being passed call by value. Now, if insteadwe had the following function prototype.

    void func(const int *& iPtr);

    Now iPtr is being passed call by reference, and therefore the compilerwould complain if we tried to pass xPtr to this function. Of course

    xPtr could be passed to the following function with no problem.

    void func(const int * const & iPtr);

    Example 6:

    class myClass {public:void memFunc(myClass & obj2) const // This const protects the// object invoked with this method.{obj2.dataMem = 10; // Object obj2 is not protected by

    // making memFunc() const. No error will be generated.this->dataMem = 10; // This is NOT allowed.}private:int dataMem;};

    int main(){myClass x,y;x.memFunc(y);return 0;}

    error C2166: l-value specifies const object

    Example 7:

    class myClass {public:const int & memFunc(int & iRef) // This const protects the// reference being returned by the method.{return iRef;}private:int dataMem;};

    int main(){int y;myClass x;x.memFunc(y) = 10; // This is NOT allowed. We are trying to// change the reference being returned by memFunc().return 0;}

    error C2166: l-value specifies const object

  • 8/3/2019 The Second Const Used for CProgr

    4/6

    Would the following change to main() also generate an error?

    int & z = x.memFunc(y);

    The answer is yes! Not because we are trying to modify the referencereturned by memFunc(), but because we are assigning that reference toanother reference which is not const. The following statement would

    be ok.

    const int & z = x.memFunc(y);

    Now z is a const reference, and is "promising" to not modify the constreference being assigned to it.

    Would the following statement also generate an error?

    int z = x.memFunc(y);

    No. In this case, only a copy of the reference being returned by

    memFunc() is assigned to z. Modifying z will not modify the referencewhich was returned by memFunc().

    Example 8:

    This example is actually an extension of Example 2.

    void func(const int & val) // This const protects val from being// modified inside this function.{val = 20; // This is NOT allowed.}

    int main(){int x =10;func(x);return 0;}

    error C2166: l-value specifies const object

    In case you are wondering, even if val were passed to func() as a callby value rather than as a call by reference, val may still NOT bemodified inside of func().

    Example 9:

    class myClass {public:myClass (void) { //default ctorthis->year = 1970;this->month = 1;this->day = 1;}myClass (int y, int m = 1, int d = 1){ // conversion ctorthis->year = y;this->month = m;

    this->day = d; }

    void memFunc (){} // non const member function does nothing

  • 8/3/2019 The Second Const Used for CProgr

    5/6

    private:int year;int month;int day;};

    int main(){const myClass defaultObj; // use default ctor// to create const objectconst myClass bDay(1956,04,25); // create a second const object

    defaultObj.memFunc();// This is NOT allowed since// memFunc() is not constbDay.memFunc();// This is NOT allowed since// memFunc() is not const

    return 0;

    }

    error C2662: 'myClass::memFunc' : cannot convert 'this' pointer from'const myClass' to 'myClass &'

    error C2662: 'myClass::memFunc' : cannot convert 'this' pointer from'const myClass' to 'myClass &'

    If we wish to create a const object of a user defined class, we musthave a constructor that can initialize the object exactly as we needit to be, since we will not be able to modify the object after it hasbeen "constructed".

    Note that in the sample code above, if we had declared the 3 datamembers to be public instead of private, we would still not have beenable to change the value of the members of the defaultOBJ and bDayobjects in main(), because these objects are const.

    Miscellaneous Point 1:

    The following will generate some compile errors.

    int main(){int SIZE = 10; // SIZE is not constint y[SIZE]; // SIZE is not a constant, so NOT allowed.return 0;}

    If we make SIZE const, the compiler is now happy.

    int main(){const int SIZE = 10; // SIZE is now constint y[SIZE]; // SIZE is now a constant, so it is allowed.return 0;}

    Miscellaneous Point 2:

  • 8/3/2019 The Second Const Used for CProgr

    6/6

    We are normally not allowed to initialize a data member inside a classdeclaration in C++. One exception is a const static data member ofintegral type. By integral type we mean types char, short, int, longor long long. Type double for example is NOT an integral type. Belowis a code snippet showing a valid example:

    class myClass {private:const static int SIZE = 100; //class variableint dataArray[SIZE]; //use class variable declared and// initialized in previous statement...

    Again, I stress that the above example works only because SIZE isstatic, const and an integral type.

    Miscellaneous Point 3:

    What is wrong with the following code example?

    class myClass {public:int & memFunc(const int & iRef){return iRef;}private:int dataMem;};

    int main()

    {const int y = 10;myClass x;x.memFunc(y);return 0;}

    Here is a hint. This code will generate the following compile error.

    error C2440: 'return' : cannot convert from 'const int' to 'int &'

    The problem is that memFunc() is trying to return iRef as a non constreference. To make the error go away, we must either return a nonreference or make the returned reference const.

    That pretty well covers my introduction to the use of const. Rememberthat one of the traits of a good C++ programmer is that they use constwhere ever possible in their code. In the long run, such a practicewill pay real dividends.