非メンバー関数がカプセル化を改善する方法の記事で、Scott Meyers は、非メンバー関数の "発生" を防ぐ方法はないと主張しています。
構文の問題
この問題について私が議論した多くの人と同じように、メンバー関数よりも非フレンド非メンバー関数を優先するべきであるという私のアドバイスの構文上の意味について留保する可能性があります。カプセル化についての議論。たとえば、Wombat クラスが食事と睡眠の両方の機能をサポートしているとします。さらに、食べる機能はメンバー関数として実装する必要がありますが、睡眠機能はメンバーまたは非友人非メンバー関数として実装できるとします。上記の私のアドバイスに従えば、次のように宣言できます。
class Wombat { public: void eat(double tonsToEat); void sleep(double hoursToSnooze); }; w.eat(.564); w.sleep(2.57);
ああ、すべての均一性!しかし、この統一性は誤解を招きます。世界には、あなたの哲学が夢見るよりも多くの機能があるからです。
率直に言えば、非メンバー関数が発生します。ウォンバットの例を続けましょう。これらのフェッチする生き物をモデル化するソフトウェアを作成し、ウォンバットが頻繁に行う必要があることの 1 つは、正確に 30 分の睡眠であると想像してください。明らかに、コードに への呼び出しを
w.sleep(.5)
散らかすことはできますが、それを入力するには大量の .5 秒が必要であり、いずれにせよ、その魔法の値が変更されたらどうなるでしょうか? この問題に対処する方法はいくつかありますが、おそらく最も簡単なのは、実行したいことの詳細をカプセル化する関数を定義することです。あなたが Wombat の作成者ではないと仮定すると、関数は必ず非 memberでなければならず、そのように呼び出す必要があります。void nap(Wombat& w) { w.sleep(.5); } Wombat w; nap(w);
そして、あなたの恐ろしい構文の矛盾があります。ウォンバットに餌をやりたいときはメンバー関数呼び出しを行いますが、昼寝させたいときは非メンバー呼び出しを行います。
少し反省し、自分自身に正直であれば、すべてのクライアントが必要とするすべての機能を備えたクラスは存在しないため、使用するすべての重要なクラスと矛盾していると主張することを認めるでしょう。すべてのクライアントは、独自の便利な関数を少なくともいくつか追加します。これらの関数は常に非メンバーです。C++ プログラマーはこれに慣れており、何も考えていません。メンバー構文を使用する呼び出しもあれば、非メンバー構文を使用する呼び出しもあります。人々は、呼び出したい関数に適した構文を調べて、それらを呼び出します。人生は続く。これは特に、標準 C++ ライブラリの STL 部分で発生します。一部のアルゴリズムはメンバー関数 (例: size)、一部は非メンバー関数 (例: unique)、一部は両方 (例: find) です。誰もまばたきしない。あなたでさえありません。
太字/イタリック体の文で彼が言っていることに頭を悩ませることはできません。非メンバーとして実装する必要があるのはなぜですか? Wombat クラスから独自の MyWombat クラスを継承し、nap()
関数を MyWombat のメンバーにしないのはなぜですか?
私は C++ を使い始めたばかりですが、おそらく Java でそれを行う方法です。これは C++ で行く方法ではありませんか? そうでない場合は、なぜですか?