メンバーおよび非メンバー関数としての演算子のオーバーロードの考えを理解するのに非常に混乱しています。
演算子を非メンバー関数としてオーバーロードするとき、実際には何を意味するのか、同様に、演算子をメンバー関数としてオーバーロードするときは何を意味するのか。非メンバー関数がフレンド関数であることは知っていますが。
メンバーおよび非メンバー関数としての演算子のオーバーロードの考えを理解するのに非常に混乱しています。
演算子を非メンバー関数としてオーバーロードするとき、実際には何を意味するのか、同様に、演算子をメンバー関数としてオーバーロードするときは何を意味するのか。非メンバー関数がフレンド関数であることは知っていますが。
演算子を非メンバー関数としてオーバーロードする場合は、操作対象のオブジェクトを引数リストで具体的に指定する必要があります。
メンバー関数としてオーバーロードすると、「this」ポインターが作業の一部を実行します。
次の例を検討してください。
class Test {
public:
friend Test operator+(const Test &lhs, const Test &rhs); // Non-member function
Test operator+(const Test &rhs); // Member function
};
2 つの違いは、非メンバー関数this
には、クラスの特定のインスタンスについて話しているときにコンパイラが便利に渡すポインターがないことです。
メンバー関数 one には、推測される lhs があるため、rhs のみを提供する必要があります。
「フレンド」は必須ではありませんが、Test のプライベート メンバーにアクセスする場合は必要です。
コンパイラは、パラメーター数に基づいて曖昧さを解消できます。を宣言したい場合friend Test operator+(const Test &rhs)
、 + は二項演算子であるため、引数が不十分であると文句を言うでしょう。メンバー関数 operator+ の lhs は " this
" です。
例
class Foo {
public:
Foo operator+(Foo) // member variant
// declared inside the function
}; // end of class
Foo operator+(Foo lhs, Foo rhs) // non-member variant
{ // declared outside the class
// could be just a call to the member variant
lhs.operator+(rhs);
// I usually do this when implementing std::stream operators,
// don't remember why just now.
}
非メンバーはフレンドになる必要はありませんが、内部状態へのアクセスが必要な場合はフレンドになる可能性があります。私が正しく覚えていれば、一部のコンパイラのテンプレート化されたコードと名前空間に関しては、非メンバーにはいくつかの利点があります。非メンバーのバリアントを友達にして、クラス外にある程度固有の関数があることを文書化することもできます。このクラスに。そのクラスを変更すると、非メンバー演算子を調べて、何も壊していないことを確認する必要があるかもしれないことがわかります。
ほとんどの演算子はメンバーとして定義する必要があります。
class MyClass
{
...
public:
const MyClass& operator+=(const MyClass&);
};
ビットこれは、次の動作と同じです。
class MyClass {...};
const MyClass& operator+=(const MyClass&, const MyClass&);
最初の例で暗黙this
的に指定されていることは、2 番目の例の最初のパラメーターに類似しています。2 番目の例で の内部状態にアクセスする必要がある場合は、edMyClass
にする必要があります。friend
class MyClass
{
friend const MyClass& operator+=(const MyClass&, const MyClass&);
};
const MyClass& operator+=(const MyClass&, const MyClass&);
これに対する典型的な例外はoperator<<
onstd::ostream
です。
std::ostream& operator<<(std::ostream&, const MyClass&);
これは論理的には のメンバーですMyClass
が、パラメーターの順序により、両方のクラスのメンバーではないか、 のメンバーである必要がありstd::ostream
ます。にはメンバーを追加できないためstd::ostream
、これは非メンバーとして定義する必要があります。
小さな例: (このコードをコンパイルしようとしたことはありませんが、うまくいくことを願っています)
class MyClass
{
public:
MyClass operator+(const MyClass& other) const; //member operator declaration
friend MyClass operator-(const MyClass& first, const MyClass& second); //non-member operator friend declaration
private:
int _a;
}
//member operator definition
MyClass MyClass::operator+(const MyClass& other) const
{
MyClass result;
result._a = _a + other._a;
return result;
}
//non-member operator definition
MyClass MyClass::operator-(const MyClass& first, const MyClass& second)
{
MyClass result;
result._a = first._a - second._a;
return result;
}
違いに注意してください: メンバー演算子の定義では、"=" の後の最初の _a の前には何も指定しません - this->_a が想定されます。
メンバー演算子関数は、クラスのインスタンスが演算子の最初の引数である場合にのみ使用できます。たとえば、のようなことをしたい場合2 + myClassObject
は、非メンバー演算子をオーバーライドする必要がありますMyClass MyClass::operator+(int first, const MyClass& second)
(または、これに必要な戻り値を使用して)。
非メンバーのオペレーターがプライベート_a
フィールドにアクセスできるようにするためだけに、フレンドシップ宣言が必要だったことにも注意してください。