2016-03-30 17 views
0

なぜこのコードが機能しないのか説明できますか? オペレータ+オーバーライド:C++演算子のオーバーライド

Fraction& Fraction::operator+(const Fraction& f) { 
    Fraction temp; 
    if (this->denominator == f.denominator){ 
     temp.numerator = this->numerator + f.numerator; 
     temp.numerator = this->numerator; 
     temp.simplifier(); 
    } 
    else { 
     temp.numerator = this->numerator * f.denominator + f.numerator * this->denominator; 
     temp.denominator = this->denominator * f.denominator; 
     temp.simplifier(); 
    } 
    return temp; 
} 

演算子=オーバーライド:RESの

void Fraction::operator=(const Fraction& f) { 
    this->numerator = f.numerator; 
    this->denominator = f.denominator; 
} 

コード後

Fraction res; 
res = f + g; 

フィールドは初期化されていない滞在します。 たとえば、コード

Fraction res = g; 

が正しく機能しています。だから演算子=(f + g)を1つのオブジェクトとして理解していないのですか?おかげさまで

+1

コンパイラはこれについて警告する必要があります。しかし '' Fraction :: operator + '' 'を使うと、ローカル変数への参照を返しています。 –

+1

'operator +'はローカル変数への参照を返します。これは未定義の動作です。'Fraction res = g;'は初期化であり、 'operator ='を呼び出すことはありません。 – user657267

+0

Fyiは、このサイトの最善の質問と回答スタックの一つであり、[** Operator Overloading **](https://stackoverflow.com/questions/4421706/operator-overloading)です。それは読む価値がある。 – WhozCraig

答えて

4

問題は、オーバーロードによってオブジェクトへの参照が返されていることです。tempは、関数が返されたときに破棄されます。

関数が返された後にそのオブジェクトにアクセスすることは定義されていません。代わりに、値によって

戻る:

Fraction Fraction::operator+(const Fraction& f) 

そして

Fraction res = g; 

を割り当てますが初期化ではなく、あなたの代入演算子を使用しません。

+1

具体的には、 'Fraction res = g;'は、もしあなたが定義していればコピー構築を、そうでなければコンパイラを提供します。 (私はコンパイラが供給しているものと思われます) –

0

スタックに作成されたテンポラリへの参照が返されます。演算子+の "temp"は、演算子+が返ったときに終了する有効期間を持ちます。その内容は、次にメソッドが呼び出されたときに、混沌とした形で変更される可能性があります。一時的に参照を返すことに加え

0

、あなたが持っている他の問題がある:

if (this->denominator == f.denominator){ 
     temp.numerator = this->numerator + f.numerator; 
     temp.numerator = this->numerator; // *HERE* 
     temp.simplifier(); 
    } 

私は* HERE *ラベルの行をする必要がありますかなり確信している:

 temp.denominator = this->denominator; 

そうでなければ初期化されていない分母を持つsimplifierを呼び出すと、悪いことが起こります。

また、operator +は、2つのFraction引数をとり、operator +=を使用する独立型バイナリ演算子にすることをお勧めします。注:lhsはコピーとして、ではなく、をconst参照として渡します。

Fraction operator +(Fraction lhs, const Fraction &rhs) 
{ 
    lhs += rhs; 
    return lhs; 
} 
0

あなたが参照として「TEMP」を返すようにしたいなら、あなたはとして「TEMP」を宣言する必要があります。

static Fraction temp; 

そして今、すべてが動作します。なぜなら、宣言の前にstaticキーワードを追加すると、プログラムが終了するまで "temp"を利用できるからです。

+0

しかし、これをしないでください。それはひどくスレッドレスで安全で、潜在的には非常に混乱させる可能性があります。 'a + b + c'は安全であると自信を持てますか? –

+0

はい私はあなたに同意します...ありがとう。 – Shiv

+0

「a + b + c + d」は '(a + b)+(c + d)'と同じ結果を与えません。 – molbdnilo