Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

a class design problem

Tags:

c++

class

In the book of "The C++ programming language", author gave the following example. He mentioned that " the cache needs to be filled before it can be used". It seems to me that this is why the function of compute_cache_value is placed. But I do not understand what does the function of string_rep( ) do in accordance with its implementation. Thanks for clarification.

class Date{
      bool cache_valid;
      string cache;
      void compute_cache_value( );  //fill cache
      // ...
public: 
      // ...
     string string_rep( ) const;
};

string Date:: string_rep( ) const
{
    if (cache_valid == false) {
          Date* th = const_cast<Date*> (this); // cast away const
          th->compute_cache_value( );
          th->cache_valid = true;
    }
    return cache;
}

In addition, the author gave the following for examples:

Date d1;
const Date d2;
string s1 = d1.string_rep( );
string s2 = d2.string_rep( );

And the author stated that the fourth example will display undefined behavior. I would like to know why.

like image 811
user630983 Avatar asked Apr 19 '26 03:04

user630983


2 Answers

string_rep checks to see if there's a cached string representation of the date. If not, it calls the compute_cache_value method to create the string representation and cache it, and then marks the cache representation as valid so future calls to string_rep don't recalculate it.

The line const Date d2; will display undefined behavior because the compiler may assume it can put d2 in nonvolatile memory (e.g. flash in a microcontroller, or read-only-flagged memory or memory-mapped memory), and the const_cast<Date*> may not work in that case, resulting in cache_valid staying false or cache staying as an empty string.

P.S. As Michael J below points out below, there are almost always better ways to do things than using const_cast. In the case of this example, the mutable keyword comes in handy. In short, marking a class member mutable tells the compiler that the member may be changed even if the object is const.

class Date
{
      mutable bool cache_valid;
      mutable string cache;
      void compute_cache_value() const;
      // ...
public: 
      // ...
     string string_rep() const;
};

string Date::string_rep() const
{
    if (cache_valid == false) {
          compute_cache_value();
          cache_valid = true;
    }
    return cache;
}

... though I'd argue that it's compute_cache_value's responsibility to set cache_valid, and I'd consider adding operator string() const { return string_rep(); } to Date.

One last thing that's neat about mutable is that the compiler has a better idea of what is going on, and in a case like d2, can put the object in volatile memory despite its declaration as const.

like image 162
Mike DeSimone Avatar answered Apr 20 '26 15:04

Mike DeSimone


string_rep() returns a string representation of the cache data. The undefined behavior in example 4 comes about because of the explicit declaration of d2 as const. const_cast can only be used (with defined behavior) to cast away implicit const'ness.

like image 34
oakley.aaron Avatar answered Apr 20 '26 15:04

oakley.aaron



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!