Ok int x = constC.Get(); // Ok: Get() is const nonConstC.Set(10); // Ok: nonConstC is modifiable constC.Set(10); // Error! Set() is a non-const method and constC is a const-qualified object } In the above code, the implicit "this" pointer to Set() has the type "C *const"; whereas the "this" pointer to Get() has type "C const *const", indicating that the method cannot modify its object through the "this" pointer. Often the programmer will supply both a const and a non-const method with the same name (but possibly quite different uses) in a class to accommodate both types of callers. Consider: class MyArray { int data[100]; public: int & Get(int i) { return data[i]; } int const & Get(int i) const { return data[i]; } }; void Foo( MyArray & array, MyArray const & constArray ) { // Get a reference to an array element // and modify its referenced value. array.Get( 5 ) = 42; // OK! (Calls: int & MyArray::Get(int)) constArray.Get( 5 ) = 42; // Error! (Calls: int const & MyArray::Get(int) const) } The const-ness of the calling object determines which version of MyArray::Get() will be invoked and thus whether or not the caller is given a reference with which he can manipulate or only observe the private data in the object. The two methods technically have different signatures because their "this" pointers have different types, allowing the compiler to choose the right one. (Returning a const reference to an int, instead of merely returning the int by value, may be overkill in the second method, but the same technique can be used for arbitrary types, as in the Standard Template Library.) Loopholes to const-correctness There are several loopholes to pure const-correctness in C and C++. They exist primarily for compatibility with existing code. The first, which applies only to C++, is the use of const_cast, which allows the programmer to strip the const qualifier, making any object modifiable. The necessity of stripping the qualifier arises when using existing code and libraries that cannot be modified but which are not const-correct. For instance, consider this code: // Prototype for a function which we cannot change but which // we know does not modify the pointee passed in. void LibraryFunc(int* ptr, int size); void CallLibraryFunc(int const * ptr, int size) { LibraryFunc(ptr, size); // Error! Drops const qualifier int* nonConstPtr = const_cast<int*>(ptr); // Strip qualifier LibraryFunc(nonConstPtr, size); // OK