137

メンバー関数として宣言されたオーバーロードされた演算子は、1つのパラメーターしか持てず、他のパラメーターが自動的に渡されるため、非対称thisであると読みました。したがって、それらを比較するための標準は存在しません。一方、aとして宣言されたオーバーロードされた演算子はfriend、同じ型の2つの引数を渡すため、対称であり、したがって、それらを比較できます。

私の質問は、ポインタの左辺値を参照と比較できるのに、なぜ友達が好まれるのかということです。(非対称バージョンを使用すると、対称バージョンと同じ結果が得られます)STLアルゴリズムが対称バージョンのみを使用するのはなぜですか?

4

2 に答える 2

167

演算子のオーバーロード関数をメンバー関数として定義すると、コンパイラは次のような式をに変換s1 + s2s1.operator+(s2)ます。つまり、演算子のオーバーロードされたメンバー関数が最初のオペランドで呼び出されます。これがメンバー関数の仕組みです!

しかし、最初のオペランドがクラスでない場合はどうなるでしょうか。最初のオペランドがクラス型ではなく、たとえば。である演算子をオーバーロードする場合は、大きな問題がありますdoubleしたがって、このように書くことはできません 10.0 + s2。ただし、のような式に対して演算子オーバーロードされたメンバー関数を記述できますs1 + 10.0

この順序付けの問題を解決するために、演算子のオーバーロード関数を、メンバーfriendにアクセスする必要がある場合として定義します。プライベートメンバーにアクセスする必要がある場合にのみ作成してください。それ以外の場合は、カプセル化を改善するために、それを非フレンド非メンバー関数にするだけです!privatefriend

class Sample
{
 public:
    Sample operator + (const Sample& op2); //works with s1 + s2
    Sample operator + (double op2); //works with s1 + 10.0

   //Make it `friend` only when it needs to access private members. 
   //Otherwise simply make it **non-friend non-member** function.
    friend Sample operator + (double op1, const Sample& op2); //works with 10.0 + s2
}

これらを読んでください:
オペランドの順序付けのわずかな問題
非メンバー関数がカプセル化をどのように改善するか

于 2011-01-07T04:17:50.497 に答える
21

グローバル演算子のオーバーロードとメンバー関数の演算子のオーバーロードの違いであるため、必ずしも演算子のfriendオーバーロードとメンバー関数の演算子のオーバーロードを区別する必要はありません。

グローバル演算子のオーバーロードを好む理由の1つは、クラスタイプが二項演算子の右側に表示される式を許可する場合です。例えば:

Foo f = 100;
int x = 10;
cout << x + f;

これは、グローバル演算子のオーバーロードがある場合にのみ機能します

Foo演算子+(int x、const Foo&f);

グローバル演算子のオーバーロードは、必ずしも関数である必要はないことに注意してくださいfriend。これは、のプライベートメンバーにアクセスする必要がある場合にのみ必要ですがFoo、常にそうであるとは限りません。

とにかく、次のようFooに、メンバー関数演算子のオーバーロードしかない場合:

class Foo
{
  ...
  Foo operator + (int x);
  ...
};

...その場合、plus演算子の左側Fooにインスタンスが表示される式のみを使用できます。

于 2011-01-07T04:12:25.690 に答える