Effective C++勉強メモ: Item 23 Non-Member Non-Friend関数をNamespaceで管理しよう
前回の項目でカプセル化の重要性について書いてあったが、そのカプセル化を最大に実現するためには、内部実装に触れることのできる面積を最小化する必要がある。
つまり、メンバ関数、フレンド関数といった「クラス内部のデータメンバに直接アクセスできる関数」をなるべく減らすのがポイントになる。クラスに最小限のAPIを定義し、そのAPIを使ったNon-Member Non-Friend関数を使ってオブジェクトとやりとりする。
そのような関数を(たとえばJavaからきたプログラマは)別のユーティリティクラスのメンバ関数にすることも多いが、C++で自然な書き方はnamespaceを使って関連性のあるクラスと関数をまとめるやり方である。
例としては:
namespace WebBrowserStuff { class WebBrowser { ... }; void clearBrowser(WebBrowser& wb); } WebBrowserStuff::WebBrowser wb; WebBrowserStuff::clearBrowser(wb);
と、本に書いてあることをまとめたが、個人的には少し微妙な気がする。APIに対する期待としてclearBrowser
はWebBrowser
オブジェクトのclear
メンバ関数であってほしい。
- 直接内部データにアクセスしなくても実装できるならそのようにするべき(実装の問題)
- そのオブジェクトのAPIはそのオブジェクトが保持するべき(プログラムの意味の問題)
というコンセプトがぶつかっている。この齟齬は、クラスという言語機構がデータアクセスと外部APIをかなり粒度の大きいレベルでしか扱っていないのが原因だろうか?
ここにすごく違和感を感じるのは、私がPythonという「データアクセスを制限する」側面を完全に放棄している言語に慣れ親しんでいるからかもしれない。