C++ operator() をメンバー関数ではなくグローバルとしてオーバーロードする必要があるのはなぜですか。たとえば、==
オペレーター。
なぜこれが行われるのですか?たとえば、STL ライブラリで。
C++ operator() をメンバー関数ではなくグローバルとしてオーバーロードする必要があるのはなぜですか。たとえば、==
オペレーター。
なぜこれが行われるのですか?たとえば、STL ライブラリで。
通常のルールは、左側のオブジェクトをメンバーに変更する演算子と、新しいオブジェクトを返す二項演算子を自由関数にすることです。後者の主な動機は、コンパイラが左辺をメンバーに一致するように変換しないためです。クラスが暗黙的な変換をサポートしている場合、通常の二項演算子はすべて自由関数にする必要があります。これにより、
左辺と右辺に同じ変換規則が適用されます。次に例を示します。
class Complex
{
public:
Complex(double r, double i = 0.0);
bool operator==( Complex const& other ) const;
};
Complex a;
// ...
if ( a == 1.0 ) // OK
// ...
if ( 1.0 == a ) // error.
しかし:
class Complex
{
public:
Complex(double r, double i = 0.0);
friend bool operator==( Complex const& lhs, Complex const& rhs ) const;
};
Complex a;
// ...
if ( a == 1.0 ) // OK
// ...
if ( 1.0 == a ) // OK
これを達成するための洗練された方法の 1 つは、メンバー関数の観点から基本操作を定義すること+
です。比較のために、結果に応じて、またはゼロを返す任意の規則、 member 、または(を定義し、次の行に沿ってテンプレートから継承する必要があります。-
operator+=
operator-=
isEqual
compare
<
==
>
template <typename T>
class ArithmeticOperators
{
friend T operator+( T const& lhs, T const& rhs )
{
T result( lhs );
result += rhs;
return result;
}
// And so on, for all of the binary operators.
};
class Complex : public ArithmeticOperators<Complex>
{
public:
// ...
Complex& operator+=( Complex const& other );
// etc.
};
関数をフリー関数にするためのいくつかの引数があることに注意してくださいoperator <op>=
: フリー関数は最初の引数として非 const 参照を取り、したがって左辺値が必要であるという事実 (組み込みの のようにoperator <op>=
)。ただし、これは通常の方法ではないようですが、おそらくoperator=
メンバーである必要があり、 をoperator <op>=
同じように扱う方が自然なようです。
私の記憶が正しければ operator =
、メンバー関数でなければなりません。に関してoperator ==
は、実際にはグローバルではなく、代わりにフリー関数を意味していると思います(STLは演算子をグローバルに定義しません)。考慮すべき点がいくつかあります。1 つは、クラス自体から分離することです。クラスのパブリック インターフェイスに関して演算子を定義できる場合は、そのように実装して、実装内部へのアクセスを維持する方がよいでしょう。最小限に。もう 1 つの基本的な利点は、型が 2 番目のオペランドになる演算子を実装できることです。型 T と U の間の等価性を考慮してください。
bool operator ==( T const& t, U const& u ){ ... }
bool operator ==( U const& t, T const& u ){ ... }
型 T と U のオブジェクトを同等に比較できる場合、 と の両方が有効であり、両方が同じ結果をもたらすt == u
ことは理にかなっています。u == t
この演算子をメンバー関数として定義していた場合、一方は T の実装内にあり、もう一方は U の実装内にあります。ここで、U は制御できないサード パーティの型であると考えてください。int
、現在、そのような演算子を提供するには、その無料の関数バージョンを提供する以外に方法はありません。
メンバー関数を引数と一致させるための規則は、フリー関数の最初の引数を一致させるための規則とは異なります。それらがどのように異なるのか正確にはわかりませんが、それらが異なるため、引数の一致が両方の引数に対して対称的に動作するように、ほとんどの二項演算子をメンバー関数ではなくフリー関数として実装することをお勧めします。
postfix++
にはexceptがありますが、それは実際には二項演算子ではなく、それと prefix を区別する方法を得るためにオーバーロードしたときにのみ再生されるため++
です。