メンバー関数として宣言されたオーバーロードされた演算子はasymmetricであり、パラメーターは1つしか持つことができず、自動的に渡されるパラメーターはthis
ポインターであるためです。したがって、それらを比較する標準は存在しません。一方、friend
として宣言されているオーバーロードされた演算子はsymmetricです。これは、同じ型の2つの引数を渡すため、比較できるためです。
私の質問は、ポインターの左辺値をまだ参照と比較できるのに、なぜ友達が好まれるのかということです。 (非対称バージョンを使用すると対称と同じ結果が得られます)STLアルゴリズムが対称バージョンのみを使用するのはなぜですか?
演算子のオーバーロード関数をメンバー関数として定義すると、コンパイラはs1 + s2
などの式をs1.operator+(s2)
に変換します。 つまり、演算子のオーバーロードされたメンバー関数は、最初のオペランドで呼び出されます。これがメンバー関数の動作です!
しかし、第1オペランドがクラスではない場合はどうでしょうか? 最初のオペランドがクラス型ではなく、double
と言う演算子をオーバーロードしたい場合、大きな問題があります。10.0 + s2
のように書きます。ただし、s1 + 10.0
などの式の演算子オーバーロードメンバー関数を作成できます。
このordering問題を解決するために、friend
メンバーにアクセスする必要がある場合、演算子のオーバーロード関数をprivate
として定義します。 プライベートメンバーにアクセスする必要がある場合にのみfriend
にしてください。それ以外の場合は単純に non-memberfunction toimproveencapsulation!
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
}
これらを読んでください:
オペランドの順序に関するわずかな問題
非メンバー関数がカプセル化を改善する方法
friend
演算子オーバーロードとメンバー関数演算子オーバーロードは、global演算子オーバーロードとメンバー関数演算子オーバーロードの間にあるため、必ずしも区別されません。
global演算子のオーバーロードを好む理由の1つは、クラスタイプがrightに表示される式を許可する場合です。 二項演算子の手側。例えば:
Foo f = 100;
int x = 10;
cout << x + f;
これは、グローバル演算子のオーバーロードがある場合にのみ機能します
Foo演算子+(int x、const Foo&f);
グローバル演算子のオーバーロードは、必ずしもfriend
関数である必要はないことに注意してください。これは、Foo
のプライベートメンバーへのアクセスが必要な場合にのみ必要ですが、常にそうであるとは限りません。
とにかく、Foo
に次のようなメンバー関数演算子のオーバーロードがある場合:
class Foo
{
...
Foo operator + (int x);
...
};
...その後、プラス演算子のleftにFoo
インスタンスが表示される式のみを使用できます。