Let’s take a brief time-out for philosophy. What does it mean for a member function to be const There are two prevailing notions: bitwise constness (also known as physical constness) and logical constness.
The bitwise const camp believes that a member function is const if and only if it doesn’t modify any of the object’s data members (excluding those that are static), i.e., if it doesn’t modify any of the bits inside the object. The nice thing about bitwise constness is that it’s easy to detect violations: compilers just look for assignments to data members. In fact, bitwise constness is C++(www.cppentry.com)’s definition of constness, and a const member function isn’t allowed to modify any of the non-static data members of the object on which it is invoked.
Unfortunately, many member functions that don’t act very const pass the bitwise test. In particular, a member function that modifies what a pointer points to frequently doesn’t act const. But if only the pointer is in the object, the function is bitwise const, and compilers won’t complain. That can lead to counterintuitive behavior. For example, suppose we have a TextBlock-like class that stores its data as a char* instead of a string, because it needs to communicate through a C API that doesn’t understand string objects.
- class CTextBlock {
- public:
This class (inappropriately) declares operator[] as a const member function, even though that function returns a reference to the object’s internal data (a topic treated in depth in Item 28). Set that aside and note that operator[]’s implementation doesn’t modify pText in any way. As a result, compilers will happily generate code for operator[]; it is, after all, bitwise const, and that’s all compilers check for. But look what it allows to happen:
Surely there is something wrong when you create a constant object with a particular value and you invoke only const member functions on it, yet you still change its value!