2011-12-05 70 views
3

我剛剛開始學習基本的C++語法,對於遇到的一段代碼我有點困惑。運算符重載C++ - 重載輸出「<<」運算符

對於一個類中創建名爲MyString的,有一個運算符重載定義爲:

ostream& operator<<(ostream& os, const MyString& s) 
{ 
    os << s.data; 
    return os; 
} 

然後在某些驅動程序功能的語句:

cout << s3 << endl; 

是跑步,其中S3是對象類型MyString的。結果打印出s3的值。

我不太明白這個聲明是如何運作的。在對它進行調整後,它看起來像是一次拷貝構造函數被調用,然後3個對象被解構。這條線如何工作?它看起來像運營商接受一個ostream和MyString的引用,但不是endl都不?還有,爲什麼只有在使用「< <」的兩個實例時纔會調用1個副本構造函數?也許我甚至沒有提出正確的問題,或者我的問題甚至沒有意義,因爲我對這些方面正在發生的事情感到困惑。如果是這樣的話,是否有人可以僅僅闡述一下正在發生的事情?

+0

你從哪裏學習C++書? –

+3

這太寬泛了,在這裏回答,你需要參考一本好書tbh。 – Nim

+0

C++ Primer 4th Ed。,by Lippman – KWJ2104

回答

7

這是一個非常普遍的問題,但我會盡量澄清你的誤解。

當你說ostream& operator<<(ostream& os, const MyString& s) { ... },你只是定義一個函數,它的ostream&作爲第一個參數和const Mystring&作爲第二個參數,並返回一個ostream&。該函數碰巧被命名爲operator<<,可通過簡寫語法x << y調用以調用operator<<(x, y)

當你做cout << s3 << endl;,這是做operator<<(operator<<(cout, s3), endl);相同。

此代碼不會調用MyString的拷貝構造函數和析構函數。你看到的消息來自其他地方。

0

MyString拷貝構造函數不需要調用此語句,因爲MyString作爲對MyString的自定義運算符< <的引用傳遞。

endl是而不是發送給定製運營商< < for MyString。

+0

所以s3 << endl沒有使用重載操作符,但cout << s3是?這是因爲s3 << endl不符合ostream&MyString&參數要求嗎? – KWJ2104

+0

沒有s3 << endl - 它是((cout << s3)<< endl)---並且第一個運算符的結果是cout。 –

1

你可以把它分解一下:

cout // this is the ostream your inserting to (stdout) 
    << s3 // this calls your defined operator that writes s.data 
    << endl; // this calls the operator<< for std::endl 

ostream& operator<<(ostream& os, const MyString& s) 
{ 
    // here os is the ostream (stdout) you're using via cout 
    // s is s3 that you passed in 
    os << s.data; // this calls operator<< for data 
    return os; // this returns the reference so the subsequent call to << endl can append to the stream 
} 
0

我想拷貝構造函數可以通過你的編譯器COUT產生。流是一個相當複雜的對象,但C++的選擇是提供這樣的語法糖(如內聯構造函數)來抽象一些細節。其他答案已經指出了使用引用的基本點,不需要爲參數傳遞執行副本。語言的

0

規則說,如果一個非成員函數(操作者< <是類MyString中的非成員函數)中相同的命名空間的MyString比可以由編譯器來選擇該非成員函數定義爲解決那個電話(正如其中一位受訪者所解釋的)我在這裏沒有使用標準術語,如果有人對這個原則有更準確的描述,請告訴我們。

+0

當我從MSVC2003切換到MSVC2005時,我有過這種行爲的直接體驗:我在這裏有類似ofstream(「log」)<<「的代碼。\ n」。切換後,而不是消息我在文件中有垃圾(指針值)。 – CapelliC