friend inline bool operator==(MonitorObjectString& lhs, MonitorObjectString& rhs) {
return(lhs.fVal==rhs.fVal);
}
friend definition
は、関数も定義するフレンド宣言であるため、と呼ばれることがあります。関数が現れるクラスを囲む名前空間の非メンバー関数として関数を定義します。実際、そこのインラインは冗長です。それがフレンド定義である場合、暗黙的にインラインで宣言されます。それのいくつかの長所と短所:
- これにより、オペレーターは通常のルックアップでは見えなくなります。これを呼び出す唯一の方法は、引数依存のルックアップを使用することです。これにより、名前空間に多くの演算子宣言が表示されなくなります。これにより、MonitorObjectString への暗黙的な変換を使用して呼び出す機能も無効になることに注意してください (呼び出される候補を探すときに両方の引数の型が一致しない場合、引数に依存する検索では関数が見つからないため)。
- 名前の検索は、フレンド定義が表示されるクラスのスコープで開始されます。これは、長い型名やその他の名前を書き出す必要がないことを意味します。クラスの通常のメンバー関数で行うように、それらを参照するだけです。
- 友達なので、関数は の内部を見てい
MonitorObjectString
ます。しかし、それは良い悪いではありません。状況によります。たとえばgetFVal()
、関数を友達にする関数がある場合、かなり無意味です。getFVal
同様に使用できます。
私は以前、このフレンド定義スタイルのオペレーターが好きでした。なぜなら、オペレーターはクラス メンバーに直接アクセスでき、クラス定義内に表示されるため、「一目ですべて」を取得できたからです。しかし、最近になって、それが常に良い考えであるとは限らないという結論に達しました。純粋にクラスのパブリック メンバー関数を使用してオペレーターを実装できる (実装すべきである) 場合は、クラスの同じ名前空間で定義された非フレンド (および非メンバー) オペレーターにする必要があります。実装の一部を変更しても、クラスのインターフェースは同じままにしておいても、オペレーターは引き続き機能し、実装の詳細にアクセスできないことがわかっているため、カスケード変更が少なくなります。
ただし、名前空間スコープの演算子関数には、引数と対称であるという追加機能があるため、メンバー演算子を記述するよりもこのスタイルを好みます。左側は特別に扱われません。両側は通常の引数であり、オブジェクト引数ではないためです。にバインドされてい*this
ます。左側または右側のどちらかがクラスの型である場合、左側か右側かに関係なく、反対側を暗黙的に変換できます。フレンド定義構文を使用せずに (伝統的に名前空間スコープで) 定義されている関数については、それらの演算子を使用可能にするかどうかを示すヘッダーを選択的に含める機能があります。