privateメンバーの書き換えを防止するには?

解決


boze  2006-10-19 23:25:02  No: 63367

privateなメンバー変数として文字列や別のオブジェクトを持っている場合に
それへの参照を返すpublicなメンバー関数を作りたいのですが
使用時にconstを外されるとメンバー変数を書き換えられてしまいます。

これを防ぐ良い方法はないでしょうか?
あきらめてコピーインスタンスを返すべきでしょうか?

環境:VC++ 2005

コード例:
-------------------------------------------------
#include <iostream>
#include <string>

class hoge
{
public:
    hoge( const std::string& s ) : m_str( s ) {}

    const std::string& GetStr() const
    {
        std::cout <<  "m_str: " << m_str << std::endl;
        return m_str;
    }

private:
    std::string m_str;
};

int main( int argc, char* argv[] )
{
    hoge h( "aaa" );

    const std::string& ss = h.GetStr();
    std::cout <<  "ss: " << ss << std::endl;

    const_cast<std::string&>( ss ) = "bbb"; // 危険

    std::cout << "GetStr: " << h.GetStr() << std::endl;
}
-------------------------------------------------

結果:
-------------------------------------------------
m_str: aaa
ss: aaa
m_str: bbb
GetStr: bbb
-------------------------------------------------


キー  2006-10-19 23:32:18  No: 63368

試していませんが
=演算子をオーバーロードして、且つそれをprivateにするとか


tetrapod  2006-10-19 23:57:01  No: 63369

C/C++ ってそういう言語。
const_cast で const 外すってのがそもそも極めてヤクザな行動。
だけどその必要があるときには極道な行動でもできるようになってる。

あなた以外のプログラマの良識に期待して
「まっとうなプログラマならそういう激悪なことはしないだろう」
と現状どおりにメンバへの参照を返す選択をするもよし。

逆に、あなた以外のプログラマはすべて性悪とみなしてコピーを返すもよし。

俺ならクラスの解説ドキュメントに const 外したら以後の動作は未定義
と書いておき、メンバへの参照を返すかなぁ。

# そのメンバ変数のコピーに必要な速度と
# 当該メンバ関数の利用頻度を考察するほうが
# 決定的に先だと思うが

複数のメンバが相互に関連を持っていて、片方だけ勝手に書き換えられたら
誤動作するってのは別に普通の話だと思う。そういう場合は、俺なら
コピーを返すか、そもそも完全隠蔽すると思う。


boze  2006-10-20 00:26:51  No: 63370

キーさん

=演算子を使う必要がない場合は有用かもしれませんね。
ありがとうございます。

tetapodさん

やっぱりそうですよね。。。
何でもできるとこが良くも悪くもC++ですね。

利用頻度とコピーのコストを考えると
備忘録がてら注意書きも残して
今のまま参照を返すことにします。

ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加