質問

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

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

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

どう思いますか?「友達」って駄目なの?

役に立ちましたか?

解決

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

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

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

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

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

他のヒント

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

文法的には話す...

friendキーワードはまだ、この関数は、クラスのメンバーではないコンパイラを伝えるために必要とされている編集の代わりに、クラスのprivateメンバーを見ることができる非メンバ関数。

<時間>

しかし、これはこのように、よりきれいに実装されている可能性があります:

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

(もちろん、私はfValそのCONSTネスに影響を与えることなく、比較することができる適切なタイプのものであると仮定しています。)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top