2012-11-29 76 views
1

我很抱歉我複製了this question,但我沒有評論的聲望以及那裏沒有令人信服的答案。過載後'std :: endl'的'operator <<'不匹配

#include<iostream> 

class my_ostream : public std::ostream 
{ 
    public: 
    std::string prefix; 

    my_ostream():prefix("*"){} 

    my_ostream& operator<<(const std::string &s){ 
     std::cout << this->prefix << s; 
     return *this; 
    } 
}; 

int main(){ 
    my_ostream s; 
    std::string str("text"); 
    s << str << std::endl; 
} 

在這裏,我得到:

在「s.my_ostream ::運算敵不過 '操作< <' < <(((常量的std :: string &)((常量性病: :字符串*)(& STR))))< <的std :: ENDL」

,我不明白爲什麼。如果它適用於ostream,它應該適用於my_ostream。這個程序的工作原理:

#include <iostream> 
using namespace std; 

class a{}; 
class b:public a{}; 
class c:public b{}; 

void f(a){cout << 'a' << endl;} 
void f(b){cout << 'b' << endl;} 
void f(b, a){cout << "b, a" << endl;} 
void f(c){cout << 'c' << endl;} 
void f(c, int){cout << "c, int" << endl;} 

void f(a*){cout << "pa" << endl;} 
void f(b*){cout << "pb" << endl;} 
void f(b*, a*){cout << "pb, pa" << endl;} 
void f(c*){cout << "pc" << endl;} 
void f(c*, int){cout << "pc, int" << endl;} 

int main(){ 
    a ao; b bo; c co; 
    f(ao); f(bo); f(co); 
    f(co, ao); 
    a *pa=new(a); b *pb=new(b); c *pc=new(c); 
    f(pa); f(pb); f(pc); 
    f(pc, pa); 
    return 0;} 

它輸出:

a 
b 
c 
b, a 
pa 
pb 
pc 
pb, pa 

那麼簡單超載並不能解釋這個錯誤。另外,我不在這裏介紹模板,所以未確定的模板類型參數不應該發揮作用。閱讀iostream代碼證明是非常困難的,所以我非常感謝任何見解。

+0

事實證明'std :: ostream s;'也不起作用,所以這是相當複雜和難以理解的。 –

+0

互聯網說'cout'是'ostream'類型的,但是。任何人都可以解開這個節點? :) –

回答

2

簡單重載確實解釋此錯誤。實際上,std::cout只是使問題複雜化。下面的方式也行不通:

int main(){ 
    my_ostream s; 
    s << 1; 
} 

的問題是,你的operator <<過載效果隱藏所有的基類中定義的過載。

粗略地說,C++在作用域解析後會重載解析。所以C++首先檢查在你的類的範圍內是否定義了一個operator <<。有!因此,它停止在那裏搜索更多的通用函數,只考慮已經爲重載解析找到的函數。唉,只有一個過載,因爲std::string,所以通話失敗。

這可以簡單地通過定義operator <<不是作爲一個成員函數,但自由的功能是固定的:

my_ostream& operator<<(my_ostream& out, const std::string &s) { 
    std::cout << out.prefix << s; 
    return out; 
} 

...但當然,這只是修復了一些你的問題,因爲你的類定義僅僅是語義錯誤的;你不能像這樣繼承IO流。在這裏,我的知識失敗,但我認爲爲了做你想做的事情,你應該覆蓋流緩衝區的功能uflow

+1

謝謝你的回答。我不能相信C++不會重載繼承的函數(它不會,我驗證過),我不相信我不知道它。很高興知道ostream不會被分類。將'operator <<'從my_ostream中取出後,程序編譯完成,但是當它到達'std :: endl'時,它會拋出一個'std :: bad_cast'。請告訴我爲什麼會發生這種情況。 uflow似乎只爲文件定義,'filebuf :: uflow'。也許我應該重寫'std :: streambuf :: sputc'並從重寫函數中調用它? –

相關問題