2012-04-08 66 views
5

我想教自己C++,並且我正在經歷一個關於構造函數的基本練習。我有一個程序,它被意外地表現:C++:構造函數的麻煩

Fraction.h:

#include <iostream> 

#ifndef FRACTION_H 
#define FRACTION_H 

using namespace std; 

class Fraction 
{ 
private: 
    int num; 
    int denom; 
    static int gcd(int a, int b); 
    void reduce(); 
public: 
    Fraction(int n=0, int d=1); 
    Fraction(Fraction& f); 
    ~Fraction(); 

    Fraction& operator=(const Fraction& f); 

    friend Fraction operator+(const Fraction& f1, const Fraction& f2); 

    friend ostream& operator<<(ostream& out, const Fraction& f); 
}; 

#endif // FRACTION_H 

Fraction.cpp(一些實施方式中被省略):

#include "../include/Fraction.h" 

#include <cassert> 
#include <iostream> 

using namespace std; 

int Fraction::gcd(int a, int b) { 
    // implementation omitted 
} 

void Fraction::reduce() { 
    // implementation omitted 
    // this just reduces fractions to lowest terms, like 3/6 to 1/2 
} 

Fraction::Fraction(int n, int d) { 
    cout << "new fraction, n=" << n << ", d=" << d << endl; 
    assert(d != 0); 
    if (d < 0) { 
     num = -n; 
     denom = -d; 
    } else { 
     num = n; 
     denom = d; 
    } 
    reduce(); 
} 

Fraction::Fraction(Fraction& f) { 
    cout << "copy fraction " << f << " at " << &f << endl; 
    num = f.num; 
    denom = f.denom; 
} 

Fraction::~Fraction() { 
} 

Fraction& Fraction::operator=(const Fraction& f) { 
    cout << "assign fraction to " << f << " at " << &f << endl; 
    if (this == &f) 
     return *this; 
    num = f.num; 
    denom = f.denom; 
    return *this; 
} 

Fraction operator+(const Fraction& f1, const Fraction& f2) { 
    cout << "adding " << f1 << " and " << f2 << endl; 
    return Fraction(f1.num * f2.denom + f2.num * f1.denom, 
        f1.denom * f2.denom); 
} 

ostream& operator<<(ostream& out, const Fraction& f) { 
    out << f.num << "/" << f.denom; 
    return out; 
} 

main.cpp中:

#include "include/Fraction.h" 

#include <iostream> 

using namespace std; 

int main() 
{ 
    Fraction f1(1, 3); 
    Fraction f2(1, 2); 
    cout << f1 << endl; 
    cout << f2 << endl; 
    cout << (f1 + f2) << endl; 
    return 0; 
} 

當我運行這個時,前兩個打印語句輸出1/31/2如預期,但第三個打印0/1而不是5/6。從我的調試語句中,我通過Fraction(int, int)構造函數創建了5/6,但由於某種原因,它隨後被調用了0/1。當我刪除複製構造函數時,代碼打印出5/6。這裏發生了什麼,以及如何在不刪除複製構造函數的情況下修復它?

+0

太多的代碼負責該問題缺失。你可以發佈代碼的其餘部分,還是創建一個可以展示問題的完整的可編譯示例? – 2012-04-08 23:47:35

+1

嘿,出於好奇 - 你使用哪種編譯器?我很感興趣的是如何讓它首先允許缺少'const'。 – 2012-04-09 02:27:28

回答

7

您的拷貝構造函數簽名應該爲

Fraction(const Fraction&); 

Fraction(Fraction&); 

當你做return Fraction(...);,編譯器必須調用Fraction(const Fraction&)因爲返回的分數是暫時的,但既然你沒有定義它,你的編譯器會發生奇怪的事情。您的編譯器行爲異常,並允許您以某種方式使用默認的構造函數,當它發出錯誤時。用gcc編譯你的代碼是行不通的,你必須進行我提到的修改,並且應該修復它。

此外,您的編譯器未在該函數上使用RVO的事實表明您使用的是非常舊的和/或糟糕的編譯器。

+0

+1我第二個這個,這絕對是答案。 – 2012-04-08 23:53:23

+0

謝謝!增加'const'使它工作。 – user1320895 2012-04-08 23:54:49

+3

嗨@ user1320895,我看你是StackOverflow的新手。既然您確定這是正確的答案,請確保您按下此答案上的「接受」複選標記,即此處的禮節。 (我被允許成爲提醒你的人,因爲我沒有發佈實際答案:-))。 – 2012-04-08 23:56:32