2016-11-22 63 views
1

對於什麼樣的返回類型成員與非成員函數應該有什麼「規則」?會員與非會員功能,退貨複印或參考?

我正在構建一個複雜類,我認爲成員函數是返回類型引用,非成員將是副本。它是否正確?

Complex.h供參考:

#include <iostream> 
#include <string> 

#ifndef COMPLEX_H 
#define COMPLEX_H 


class Complex { 

    public: 
    double real; 
    double imaginary; 


    Complex(); 
    Complex(const double real); 
    Complex(const double real, const double imaginary); 
    Complex(const Complex &rhs); 

    Complex& operator *= (const Complex&); 
    Complex& operator += (const Complex&); 
    Complex& operator /= (const Complex&); 
    Complex& operator -= (const Complex&); 
    Complex& operator = (const Complex&); 

}; 

class Complex; 

double abs(const Complex& c); 

Complex operator * (const Complex& c1, const Complex& c2); 
Complex operator/(const Complex& c1, const Complex& c2); 
Complex operator + (const Complex& c1, const Complex& c2); 
Complex operator - (const Complex& c1, const Complex& c2); 

bool operator == (const Complex& c1, const Complex& c2); 
bool operator != (const Complex& c1, const Complex& c2); 

std::istream& operator >> (std::istream& in, Complex& c); 
std::ostream& operator << (std::ostream& out, const Complex& c); 

Complex operator ""_i(long double arg); 
Complex operator ""_i(unsigned long long arg); 

#endif 
+2

相關的,你可能會從你似乎正在重塑的['std :: complex'](http://en.cppreference.com/w/cpp/numeric/complex)類中獲得一些相當不錯的指導。標準圖書館建築師有機會做出一些經過深思熟慮的選擇。 – WhozCraig

回答

2

這不是真正的成員與非成員。您在成員函數中返回引用,因爲它們實際上修改了this值。

考慮下面的代碼:

Complex c1, c2, c3; 
// ... 
(c3 *= c2) += c1; 

這裏c3 *= c2將被評估,然後operator+=將被稱爲與c1作爲參數的結果。如果您返回c3 *= c2的副本而不是參考,則下一個應用的operator+=將修改此返回的副本,而不是c3,這不是人們所期望的。你可以聲明瞭其他運營商的成員函數爲好,只是爲了顯示參考VS副本

注意是沒有關係的成員與非成員:

class Complex { 

    // ... 

    Complex& operator *= (const Complex&); 
    Complex& operator += (const Complex&); 
    Complex& operator /= (const Complex&); 
    Complex& operator -= (const Complex&); 
    Complex& operator = (const Complex&); 

    Complex operator * (const Complex& c2); 
    Complex operator/(const Complex& c2); 
    Complex operator + (const Complex& c2); 
    Complex operator - (const Complex& c2); 

}; 
2

你要看看你當你給你的操作員打電話時,你會期望結果。

例如,如果您使用操作符*,你會希望有可能

//Some Complex instances c1 and c2 already created 
Complex c3 = c1 * c2; 

你不會希望有C1或C2修改。所以這裏的副本很好。

但是,如果您使用運算符* =,則期望結果修改調用該運算符的複雜實例。所以在這裏,參考更好,因爲你會避免複製構造函數和析構函數。

所以你給的例子可以。

2

就像上面我說的那樣,重要的問題不在於這是成員還是非成員,而是返回的值是否是新實例。

任何改變對象本身的操作(如++,+ =, - =,...)都應該返回對同一對象的引用。另一方面,任何導致另一個對象(如二進制+, - 等等)的操作都必須創建一個新對象,因爲原始操作數不應該改變。此外,你可以有一些二元運算符是成員(例如complex + int),而其他的則必須在類外部定義(例如,int + complex)。當然,你希望這兩個操作的行爲是一致的。