2017-10-28 88 views
2

如果<<運算符超載的返回類型爲std::string,我很難理解編譯器控制錯誤的原因。你能幫我理解嗎?錯誤<<運算符重載返回一個std ::字符串

波紋管是一個可重現的例子,它給出了一個巨大的錯誤。

class XY 
{ 
    int X__; 
    int Y__; 
public: 
    XY(int x, int y):X__(x), Y__(y){} 
    ~XY(){} 

    std::string operator<<(const XY_cartesiano& c) 
    { 
     std::stringstream ss; 
     ss << "{ " << X__ << ", " << Y__ << " }"; 
     return ss.str(); 
    } 

    int x() const{return X__;} 
    int y() const{return Y__;} 
}; 

void main() 
{ 

XY a(1,2); 
std::cout << a; 
} 
+1

這是沒有問題的,但包含兩個連續的下劃線('X__','Y__')和名稱的名稱以下劃線跟着一個大寫字母開頭保留供實施使用。不要在你的代碼中使用它們。 –

回答

3

讓我們這樣的事情作爲一個例子:

cout << "My number is " << 137 << " and I like it a lot." << endl; 

這被分析爲

((((cout << "My number is ") << 137) << " and I like it a lot.") << endl); 

尤其注意到表達cout << "My number is "必須評估的東西,這樣,當然後我們嘗試插入137與<< 137的含義是「請137並將其發送到cout」。

想象一下,如果cout << "My number is "要返回string。在這種情況下,<< 137位會嘗試在左側的string與右側的int之間使用<<運算符,這在C++中沒有很好定義。

約定是讓流插入運算符operator <<返回對左側流的引用,以便這些操作鏈接良好。這樣,<< 137左側的東西本身就是cout,所以上面的代碼基本上是一系列鏈接調用來插入cout。因此,這些功能的簽名通常如下所示:

ostream& operator<< (ostream& out, const ObjectType& myObject) { 
    // ... do something to insert myObject into out ... // 
    return out; 
} 

現在,一切正常鏈接。注意這個函數是一個自由函數,不是成員函數,左邊是ostream類型,右邊有你的類的類型。這是做這件事的傳統方法,因爲如果你嘗試將operator <<作爲成員函數進行重載,那麼左邊將是你類類型的操作數,這與流插入應該如何工作相反。如果您需要專門訪問類的私有領域在實現此功能的過程中,使之成爲朋友:

class XY { 
public: 
     ... 
     friend ostream& operator<< (ostream& out, const XY& myXY); 
}; 

ostream& operator<< (ostream& out, const XY &myXY) { 
    ... 
    return out; 
} 
1

正確方法重載<<運營商,你的情況是

ostream& operator<<(ostream& os, const XY& c) 
{ 
    os << c.X__ <<" "<< c.Y__ ; 
    return os; 
} 
+0

實際上,如果'os'設置了其寬度修飾符(或其他瞬態流修飾符),以便輸出不會部分損壞,那麼使用內部'ostringstream'可以構建一次打印的整個字符串。 – templatetypedef

1

你有重載operator<<的方式與當您打算將對象(如std::cout)使用該操作符時必須遵循的約定不符。

事實上,您的operator<<的簽名與流無關!它只是XY的成員函數,它需要另一個XY(它不使用它),返回一個字符串並具有一個非名稱。這裏是你如何在理論上稱之爲:

XY a(1,2); 
XY b(1,2); 
std::string x = (a << b); 

超載operator<<爲使用流,正確的方法是使運營商在非成員函數中,添加一個流的參考參數和返回流參照流參數。你也不需要字符串流;你直接寫入到流你:

#include <iostream> 

class XY 
{ 
    int x; 
    int y; 
public: 
    XY(int x, int y) : x(x), y(y) {} 

    int X() const { return x; } 
    int Y() const { return y; } 
}; 

std::ostream& operator<<(std::ostream& os, XY const& c) 
{ 
    os << "{ " << c.X() << ", " << c.Y() << " }"; 
    return os; 
} 

int main() 
{ 
    XY a(1,2); 
    std::cout << a; 
}