27

ヘッダーに、自分で次のように書いていないことがわかります。

class MonitorObjectString: public MonitorObject {
   // some other declarations
   friend inline bool operator==(MonitorObjectString& lhs, MonitorObjectString& rhs) { return(lhs.fVal==rhs.fVal); }

このメソッドがフレンドとして宣言されている理由がわかりません。関数が別の場所で定義されていて、クラスの内部メンバーにアクセスする必要がある場合は理にかなっていると思いましたが、インラインでメンバーにアクセスする必要さえないため、ここではそうではありません。

どう思いますか?「友達」はダメですか?

4

3 に答える 3

52
friend inline bool operator==(MonitorObjectString& lhs, MonitorObjectString& rhs) { 
    return(lhs.fVal==rhs.fVal); 
}

friend definitionは、関数も定義するフレンド宣言であるため、と呼ばれることがあります。関数が現れるクラスを囲む名前空間の非メンバー関数として関数を定義します。実際、そこのインラインは冗長です。それがフレンド定義である場合、暗黙的にインラインで宣言されます。それのいくつかの長所と短所:

  • これにより、オペレーターは通常のルックアップでは見えなくなります。これを呼び出す唯一の方法は、引数依存のルックアップを使用することです。これにより、名前空間に多くの演算子宣言が表示されなくなります。これにより、MonitorObjectString への暗黙的な変換を使用して呼び出す機能も無効になることに注意してください (呼び出される候補を探すときに両方の引数の型が一致しない場合、引数に依存する検索では関数が見つからないため)。
  • 名前の検索は、フレンド定義が表示されるクラスのスコープで開始されます。これは、長い型名やその他の名前を書き出す必要がないことを意味します。クラスの通常のメンバー関数で行うように、それらを参照するだけです。
  • 友達なので、関数は の内部を見ていMonitorObjectStringます。しかし、それは良い悪いではありません。状況によります。たとえばgetFVal()、関数を友達にする関数がある場合、かなり無意味です。getFVal同様に使用できます。

私は以前、このフレンド定義スタイルのオペレーターが好きでした。なぜなら、オペレーターはクラス メンバーに直接アクセスでき、クラス定義内に表示されるため、「一目ですべて」を取得できたからです。しかし、最近になって、それが常に良い考えであるとは限らないという結論に達しました。純粋にクラスのパブリック メンバー関数を使用してオペレーターを実装できる (実装すべきである) 場合は、クラスの同じ名前空間で定義された非フレンド (および非メンバー) オペレーターにする必要があります。実装の一部を変更しても、クラスのインターフェースは同じままにしておいても、オペレーターは引き続き機能し、実装の詳細にアクセスできないことがわかっているため、カスケード変更が少なくなります。

ただし、名前空間スコープの演算子関数には、引数と対称であるという追加機能があるため、メンバー演算子を記述するよりもこのスタイルを好みます。左側は特別に扱われません。両側は通常の引数であり、オブジェクト引数ではないためです。にバインドされてい*thisます。左側または右側のどちらかがクラスの型である場合、左側か右側かに関係なく、反対側を暗黙的に変換できます。フレンド定義構文を使用せずに (伝統的に名前空間スコープで) 定義されている関数については、それらの演算子を使用可能にするかどうかを示すヘッダーを選択的に含める機能があります。

于 2008-12-19T20:08:19.913 に答える
7

文法的に言えば...

キーワードは、この関数がクラスのメンバーではなく、クラスのプライベートメンバーを参照できる非メンバー関数であることをfriendコンパイラに伝えるために引き続き必要です。


ただし、これは次のようにもっときれいに実装できた可能性があります。

/* friend */ inline bool operator ==(const MonitorObjectString& rhs) const
{ return fVal == rhs.fVal; }

(もちろん、fValconst 性に影響を与えずに比較できる適切な型であると想定しています。)

于 2008-12-19T14:58:41.600 に答える
6

それらは相互に排他的ではありません。「フレンド」は、非メンバー関数がクラスのプライベート メンバーにアクセスできることを意味します。「インライン」は、関数呼び出しの呼び出しがないことを意味し、関数の本体はすべての呼び出しサイトで (アセンブリで) 複製されます。

于 2008-12-19T14:58:47.557 に答える