[迷信] コンパイルエラーが出るのでアクセス指定子を修正

C++を使ってチームで開発していると、一度ぐらいは必ず遭遇したことがある恐怖の間違いがあります。それが、コンパイルエラーを取り除くためにアクセス指定子を修正すればよいという考え方です。具体的にどういうことか見ていきましょう。

class foo
{
public:
  ...
private:
  int bar_;
};

上のようなクラス定義があったとします。このクラスでは、セオリー通りデータメンバを非公開にしています。そして、データメンバ bar_ は、メンバ関数を呼び出したときに適切に操作されるようになっていると考えてください。get_bar や set_bar のようないわゆるアクセッサは設けず、あくまでも foo クラスの実装の詳細という位置づけです。

この foo クラスのクライアントコードを書いている担当者が、foo クラスを何とか使いこなそうとして、実装を理解するためにソースコードを読むことはよくあります。クラスはブラックボックスとして考えればよいなどという建前論は大抵無意味です。遅かれ早かれ、彼は foo クラスの内部状態を保持しているデータメンバ bar_ を見つけることでしょう。そして、この bar_ の値を外部から参照したいと考えるかもしれません。

C++に不慣れなのか、private というアクセス指定子を見落としたのかは知りませんが、foo クラスのクライアントコードで直接 foo::bar_ を参照するようなコードを書いてしまい、彼は、当然のことながら、コンパイルエラーに遭遇しました。エラーメッセージを見てすぐに、エラーの原因が foo::bar_ が private だからということに気付きました。

ここから問題行動が始まります。

foo::bar_ は private であり、外部から参照することはできません。ですので、この値を参照してどうにかするというのは、そもそもの設計に問題があるわけです。しかし、彼がこれまでに書いたコードは foo::bar_ の値を参照できることに強く依存しており、今さらそれらを全部捨てて書き直すのは大変です。そこで、こっそり private を public に書き換えてしまいます。これで彼が書いたコードはコンパイルに成功し、期待通りに動作しました。"彼は"万々歳です。

こんな冗談のようなことが実際にはしばしば発生します。データメンバを private にしていたのは、彼のような無茶をする相手からオブジェクトを保護するために、foo クラスの設計者がそのようにしたわけです。いわば、foo クラスの免疫機構のようなものです。彼の行為はその免疫機構を破壊する行為であり、foo クラスとそのオブジェクトを病原菌(=オブジェクトを破壊するようなクライアントコードによる間違った操作)に対して無防備にしてしまいます。

foo::bar_ が public になれば、今や自在に foo::bar_ を外部から変更できるようになってしまいます。もはや破綻は時間の問題です。

この記事のトラックバックURL:

http://www.kijineko.co.jp/trackback/598
このエントリーを含むはてなブックマーク