December 23, 2003

constだらけのC++

バイトの関係で、C++を最近使い始めました。一週間が経ちSTLぐらいまでは速習で使いこなせるようになったみたいですが、ここで問題発生。C++特有のconstで混乱しました。

もともとがJavaプログラマゆえ、クラスのカプセル化には異常なまでにこだわりをもってC++のコードを書いていました。その情熱がconstにも向けられたため大変なことに。

#include <necessaryHeader>

class Hoge{
    private:
        Ada *ada;        
    public:
        Hoge(){ada = new Ada();}
        ~Hoge(){delete ada;}
        const Ada *getAda() const{return ada;}
}

class Ada{
    private:
        bool flag;
        bool switch(){return (flag = !flag);}
    public:
        Ada(){flag = true;}
        const bool getFlag() const{return flag;} //←OK
        const bool getFlagSwitched(){return switch();} //←Compile Error
}

int main(){
    Hoge hoge();
    const Ada *ada_hoge = hoge.getAda();
    cout << ada_hoge->getFlag() << endl;
    cout << ada_hoge->getFlagSwitched() << endl;
}


簡単に説明するとクラスHogeのインスタンスから得られたAda *の内容は大抵の場合変更したくはないが、一部だけ(この場合flag)変更することを許したい場合。このためにflagを変更するAda::switch()ではswitch() const{}とせずにswitch(){}とし、それを呼び出すAda::getFlagSwitched()ではconst{}としていませんが、こうすると『型があわない』とコンパイラに文句をいわれます。どうすればいいか??
ここでキャストconst_castの登場です。これを使用することによって一次的にconstをキャンセルすることができます。使い方はconst_cast<targetType>(arg)です。
例として先のコードは以下のようにすればコンパイルエラーとなりません。(Ada::getFlagSwitched()だけ変更)
const bool Ada::getFlagSwitched() const{return (const_cast<Ada *>(this))->switch();}

別の解決方法としてint main()のほうで
int main(){
    Hoge hoge();
    const Ada *ada_hoge = hoge.getAda();
    cout << ada_hoge->getFlag() << endl;
    cout << (const_cast<Ada *>(ada_hoge))->getFlagSwitched() << endl;
}

もありなんですが、ライブラリ側で対応したほうが適切だと思います。

14:15 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク | この記事をdel.icio.usでブックマーク | トラックバック
このエントリーのトラックバックURL: http://fenrir.naruoka.org/mt/mt-tb.cgi/127
コメント
コメントする









名前、アドレスを登録しますか?
(次回以降コメント入力が楽になります)
  • 匿名でのコメントは受け付けておりません。
  • 名前(ハンドル名可)とメールアドレスは必ず入力してください。
  • メールアドレスを表示されたくないときはURLも必ず記入してください。
  • コメント欄でHTMLタグは使用できません。
  • コメント本文に日本語(全角文字)がある程度多く含まれている必要があります。
  • コメント欄内のURLと思われる文字列は自動的にリンクに変換されます。