FAQ 14.12 How can a nonobservable data member be updated within a const member function?

FAQ 14.12 How can a "nonobservable" data member be updated within a const member function?

graphics/new_icon.gif

Preferably the data member should be declared with the mutable keyword. If that cannot be done, const_cast can be used.

A small percentage of inspectors need to make nonobservable changes to data members. For example, an object whose storage is physically located in a database might want to cache its last lookup in hopes of improving the performance of its next lookup. In this case there are two critical issues: (1) if someone changes the database, the cached value must somehow be either changed or marked as invalid (cache coherency); (2) the const lookup member function needs to make a change to the cached value. In cases like this, changes to the cache are not observable to users of the object (the object does not change its abstract state; see FAQ 14.09).

The easiest way to implement a nonobservable change is to declare the cache using the mutable keyword. The mutable keyword tells the compiler that const member functions are allowed to change the data member.

 int readFromDatabase() throw() { return 42; }                                       <-- 1 class Fred { public:   int get() const throw(); private:   mutable int cache_;   mutable bool cacheOk_; }; int Fred::get() const throw() {   if (! cacheOk_) {     cache_ = readFromDatabase();     cacheOk_ = true;   }   return cache_; } int main() {   Fred f;   int x = f.get();                                   <-- 2   int y = f.get();                                   <-- 3   int z = f.get();                                   <-- 4 } 

(1) Pretend this reads from the database

(2) Access the database the first time it's called

(3) Uses the cache; no database calls

(4) Uses the cache; no database calls

The second alternative is to cast away the constness of the this pointer using the const_cast keyword. In the following example, self is equal to this (that is, they point to the same object), but self is a Fred* rather than a const Fred* so self can be used to modify the this object.

 class Fred2 { public:   int get() const throw(); private:   int cache_;   bool cacheOk_; }; int Fred2::get() const throw() {   if (! cacheOk_) {     Fred2* self = const_cast<Fred2*>(this);     self->cache_ = readFromDatabase();     self->cacheOk_ = true;   }   return cache_; } 


C++ FAQs
C Programming FAQs: Frequently Asked Questions
ISBN: 0201845199
EAN: 2147483647
Year: 2005
Pages: 566
Authors: Steve Summit

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net