2017-12-13 7 views
-1

私はC++で演算子のオーバーロードがどのように機能するかを知ろうとしています。私は+==の演算子を実装する方法を理解することができましたが、私は+演算子で苦労しています。コンパイラは、オペレータは1つまたは2つの引数しか取ることができないと伝えます。私は結果を適切に返す方法を理解できないようです。C++のLHS引数を変更せずに `+`演算子を実装するには?

私が引数として取ることができるオブジェクトは、演算子のLHSとRHSですが、結果を格納して返すために、どうやらクラスの3番目のインスタンスを作成する必要があるようです。私は+オペレータがLHSかRHSのどちらかを変更しているとは思わないと思います。

さらに、メソッド内で新しいインスタンスを作成すると、メソッドが終了した後にそのオブジェクトが削除されるため、機能しません。

結果を新しいインスタンスに適切に保存するにはどうすればよいですか?

これは私がこれまで試したものです:あなたはoperator+から*thisを戻ってきている

#include <iostream> 

class smallclass 
{ 
public: 
    smallclass(); 
    smallclass(int x); 

    smallclass& operator+=(smallclass&y); 
    smallclass& operator=(smallclass& y); 
    smallclass& operator+(smallclass& y); 
    int a; 

}; 

smallclass::smallclass() 
{ 

} 

smallclass::smallclass(int x) 
{ 
    this->a = x; 
} 


smallclass& smallclass::operator+=(smallclass&y) 
{ 
    this->a += y.a; 

    return *this; 
} 

smallclass& smallclass::operator=(smallclass& y) 
{ 
    int value = y.a; 
    this->a = value; 
    return *this; 
} 


smallclass& smallclass::operator+(smallclass& y) 
{ 
    int value = y.a; 
    this->a += value; 

    return *this; 
} 


int main() 
{ 
    smallclass a = smallclass(5); 
    smallclass b = smallclass(6); 

    std::cout << a.a << std::endl; 
    std::cout << b.a << std::endl; 
    // a = 5 
    // b = 6 

    a += b; 

    std::cout << a.a << std::endl; 
    std::cout << b.a << std::endl; 
    // a = 11 
    // b = 6 

    a = b; 

    std::cout << a.a << std::endl; 
    std::cout << b.a << std::endl; 
    // a = 6 
    // b = 6 

    smallclass c; 

    c = a + b; 

    std::cout << a.a << std::endl; 
    std::cout << b.a << std::endl; 
    std::cout << c.a << std::endl; 
    // a = 12 should be 6 
    // b = 6 
    // c = 12 

    return 0; 

} 
+2

誤って何かを変更しないように、おそらく 'operator +'を 'const'にフラグを立てるべきです。あなたのオブジェクトのコピーを作成し、追加して、それを返します。 – tadman

+0

'operator ='は値を返すことができないため、動作は未定義です。 – PaulMcKenzie

+0

@PaulMcKenzie woops、固定されています。 – JAD

答えて

4

。代わりに、新しい結果を含むオブジェクトを返す必要があります。 *thisを返すと、x + yの結果は常にxであり、これは当てはまりません。結果は新しい値で、xyの両方から区別されます。戻り値は既存のインスタンスを参照していないので、戻り値の型は参照であってはならないことに注意してください。

smallclass smallclass::operator+(smallclass& y) 
{ 
    smallclass result; 
    result.a = this->a + y.a; 
    return result; 
} 

また、constについても正しく読んでください。 yconstを参照することにより、オペレーターがyを変更しないことを保証することができます。メンバー全体を機能させることについても同様です。const。オペレータがthisを変更しないことをクラスのユーザに保証します。これらがなければ、constのオペレータをconstインスタンスで使用することはできません。

smallclass smallclass::operator+(const smallclass& y) const 
{ 
    smallclass result; 
    result.a = this->a + y.a; 
    return result; 
} 

より多くの慣用的なアプローチがoperator+=のとコピーコンストラクタの用語でoperator+を実装することです。そうすれば、あなたは自分自身を繰り返す必要はありません。

smallclass smallclass::operator+(const smallclass& y) const 
{ 
    smallclass result(*this); 
    result += y; 
    return result; 
} 

これは多くのオペレータにとって可能です。特に、比較演算子はすべて、2つの基本的な比較、例えばoperator==およびoperator<のような観点から実装することができます。

+2

さらに短い例: 'return smallclass(* this)+ = y;' – PaulMcKenzie

+0

@PaulMcKenzieおそらくRVOを抑制するでしょう。 – juanchopanza

3

operator+を実装するの正規のバージョンはこれです:

friend smallclass operator+ (smallclass op1, smallclass const& op2) { 
    op1 += op2; 
    return op1; 
} 

このアプローチはまた、operator+=の既存の実装を活用可能とコピーエリジオンを活用します。あなたが可換追加については、以下のバージョンを使用することができます左側の自動変換を阻害する場合

:追加が可換されていない場合

smallclass operator+ (smallclass rhs) const { 
    rhs += *this; 
    return rhs; 
} 

あなたが使用したい

smallclass operator+ (smallclass const& rhs) const { 
    return smallclass(*this) += rhs; 
} 

(最後のバージョンでは完全に1つのコピーを削除できません)。

+0

これは、lhsの 'int'から' smallclass'への自動変換が必要であると仮定して、これは標準的です。そうでなければ、メンバーメソッドがより適切です。 –

+0

@ LokiAstari:あなたはrhsで自動変換を取得しているので、lhsでの自動変換も一貫しているように見えます。 –

+0

NRVOを除き、「可能であればコピーエリシエーションを利用する」。したがって、LHSが左辺値の場合、左辺値の参照を取り、関数の本体にコピーを作成するバージョンよりも最適ではない可能性があります。 – juanchopanza

関連する問題