と、いう訳で、const検査をかいくぐる話の続きです。
constじゃないものをconstみたいにする、…あれ?…constをconstじゃないみたいに するのかな、考え出すとどっちだかわからなくなるけど、 こういう問題のために用意されているのが、 mutableやconst_castというキーワードです。
このうちmutableは、const問題回避の小細工をしているところとは離れた場所に 書かなければならず、少々使いにくい気がするので、 const_castの方を説明します。 これは、「const問題回避のためのキャスト」という意味のキーワードなんですかね。 前回「困った例」として挙げたものは、次のように書けます。
困った例(1)
void Hoge::Open(const char * filePath) { ::LibOpen(const_cast<char *>(filePath)); // 以下省略 }
困った例(1)の2つめ
void Hoge::Open(const char * filePath) { PARAM param; param.path = const_cast<char *>(filePath); ::LibOpen(¶m); // 以下省略 }
困った例(2)
== hoge.h == class Hoge { public: virtual int GetMunya(void) const; private: boolean MunyaCalced; int Munya; }; == hoge.cpp == int Hoge::GetMunya(void) const { if (! MunyaCalced) { const_cast<Hoge *>(this)->Munya = /* いろいろ計算 */; const_cast<Hoge *>(this)->MunyaCalced = true; } return Munya; }
どうでもいいことかも知れないけど、C++に追加された構文って、不等号が 目立ちますね。 テンプレートとか、streamio の<<とか(ちょっと違う?)。
これで一応、
というような場合が解決されました。 でも、今度は、
void Hoge::SetMunya(int munya) const { const_cast<Hoge *>(this)->Munya = munya; }
みたいに
意味的にどう考えてもconstでない函数
にすらconstをつけることができてしまうんですね。 constの意味を知らず見よう見まねでconst_castを使い始めたプログラマーが、 こんなプログラムを大量生産し始めたら悲惨。 使い方を誤ると、constなんか最初から無かった方がよかった、ということに なりかねません。