// 1. const_cast
int main()
{
        const int c = 10;
        int* p2 = const_cast<int*>(&c);
// error : 원본이 const이면 벗겨내지 못한다.
        int n = 10;
        const int* p = &n;  // ok
        int* p3 = const_cast<int*>(p);
//ok : 접근 하는 놈이 const이면 벗겨 낼 수 있다.      
}
// 2. 상수함수: 멤버의값을바꿀수없다.
// const 객체는const 함수만호출가능
// 반드시멤버의값을바꾸지않는다면const 함수로만들어라.
class Point
{
        int x;
        int y;
//      string cache;
//      bool   cache_valid;
        // 상수함수내에서도값을변경할수있다.
        mutable string cache;
        mutable bool   cache_valid;
public:
        Point( int a = 0, int b = 0 ) : x(a), y(b), cache_valid(false) {}
        string to_string() const
        {
               if( cache_valid == false )
               {
                       char buf[256];
                       sprintf( buf, "%d", "%d", x, y );
                       cache = buf;
                       cache_valid = true;
               }
               return cache;
        }
};
void main()
{
        const Point p(1, 2);
        cout << p.to_string() << endl;
}
 // 3. mutable을 사용하는 대신에 논리적 상수성을 사용한다.incrementation??
 // logical constness( 논리적 상수성. ) - lazy evaluation의 기법이기도 하다.
struct cache
{
        bool valid;
        string rep;
        cache(){ valid = false; }
};
class Point
{
        int x, y;
        cache* c;
public:
        Point( int a = 0, int b = 0 ) : x(a), y(b)
        {
               c = new cache();
        }
        ~Point()
        {
               if (c != NULL)
                       delete c;
        }
        string to_string() const
        {
               if ( c->valid == false )
               {
                       char buf[256];
                       sprintf( buf, "%d", "%d", x, y );
                       c->rep = buf;
                       c->valid = true;
               }
               return c->rep;
        }
};
void main()
{
        const Point p(1, 2);
        p.to_string();
}