Sei sulla pagina 1di 6

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

Let us examine some examples of using the const keyword and the types of errors that will be generated, if we try to circumvent the protection offered by the const keyword. Note that all error messages displayed 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 y void 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 not change x's value. It does not matter that the function does not actually change x's value. If the function prototype was instead: void func( const int & y); // or void 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 not change x's value through the use of the const keyword. This is another reason why we should attempt to make parameters of a function const, so that the function can accept both const and nonconst arguments. If the function prototype was instead: void func( int y); there would also be no compile error. Why? Because now y is being passed call by value, rather than call by reference, so we don't care if the function changes the argument.

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 allowed xPtr = & 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 is declared, 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 object error 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 offered the 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 with the following prototype? void func(const int * iPtr); Yes it can! Surprised? It is because, similar to what was discussed in

Example 2 above, iPtr is being passed call by value. Now, if instead we had the following function prototype. void func(const int *& iPtr); Now iPtr is being passed call by reference, and therefore the compiler would 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

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 reference returned by memFunc(), but because we are assigning that reference to another 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 const reference 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 reference which 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 call by value rather than as a call by reference, val may still NOT be modified inside of func(). Example 9: class myClass { public: myClass (void) { //default ctor this->year = 1970; this->month = 1; this->day = 1;} myClass (int y, int m = 1, int d = 1){ // conversion ctor this->year = y; this->month = m; this->day = d; } void memFunc (){} // non const member function does nothing

private: int year; int month; int day; }; int main() { const myClass defaultObj; // use default ctor // to create const object const myClass bDay(1956,04,25); // create a second const object defaultObj.memFunc();// This is NOT allowed since // memFunc() is not const bDay.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 must have a constructor that can initialize the object exactly as we need it to be, since we will not be able to modify the object after it has been "constructed". Note that in the sample code above, if we had declared the 3 data members to be public instead of private, we would still not have been able to change the value of the members of the defaultOBJ and bDay objects 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 const int 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 const int y[SIZE]; // SIZE is now a constant, so it is allowed. return 0; } Miscellaneous Point 2:

We are normally not allowed to initialize a data member inside a class declaration in C++. One exception is a const static data member of integral type. By integral type we mean types char, short, int, long or long long. Type double for example is NOT an integral type. Below is a code snippet showing a valid example: class myClass { private: const static int SIZE = 100; //class variable int dataArray[SIZE]; //use class variable declared and // initialized in previous statement ... Again, I stress that the above example works only because SIZE is static, 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 const reference. To make the error go away, we must either return a non reference or make the returned reference const. That pretty well covers my introduction to the use of const. Remember that one of the traits of a good C++ programmer is that they use const where ever possible in their code. In the long run, such a practice will pay real dividends.

Potrebbero piacerti anche