2009-09-04 14 views
2

オートフォーマットを行う "ostream"に基づいてクラスを作成して、カンマまたはタブ区切りのファイルを生成したいとします。私の考えは、 "演算子< <"をオーバーライドして、各値の前に区切り記号(行の始めと終わりを除く)を挿入し、文字列を書き込む前に引用符を付けることでした。オーバーライドする "演算子< <"のメソッドの中で、基本クラスのメソッドを呼び出すことにしましたが、正しく動作させることはできません。ここで"ostream"から派生したクラスで "operator <<"をオーバーライドする問題

は、たとえば(G ++ 4.3.3でコンパイル)です:

#include <iostream> 
#include <ostream> 
#include <string> 

using namespace std; 

class MyStream: public ostream 
{ 
public: 
    MyStream(ostream& out): ostream(out.rdbuf()) {} 

    template <typename T> MyStream& operator<<(T value) 
    { 
    ostream::operator<<('+'); 
    ostream::operator<<(value); 
    ostream::operator<<('+'); 
    return *this; 
    } 
}; 

template<> MyStream& MyStream::operator<< <string>(string value) 
{ 
    ostream::operator<<('*'); 
    ostream::write(value.c_str(), value.size()); // ostream::operator<<(value); 
    ostream::operator<<('*'); 
    return *this; 
} 

int main() 
{ 
    MyStream mystr(cout); 
    mystr << 10; 
    cout << endl; 
    mystr << "foo"; 
    cout << endl; 
    mystr << string("test"); 
    cout << endl; 
    return 0; 
} 

2「演算子< <」方法(テンプレートと特殊化は)違った他のすべてよりも文字列を処理することがあります。しかし:

  1. 文字( '+'/'*')は数字ではなく文字として表示されます。
  2. C文字列 "foo"はメモリアドレスとして出力されます(私は思う)。
  3. "書き込み"行がコメント部分と交換された場合、コンパイラは「MyStream :: operator < <(std :: string &)への呼び出しに一致する関数がありません。明示的に基本クラスメソッドを呼び出していました。

私は間違っていますか?どんな助けでも大歓迎です。

+1

NBが含まれます。最終的には、MyStreamをヘッダーに入れる必要があります。その時点で**は 'using namespace std'を使わないでください。代わりに 'std :: ostream'のようなstlから項目を完全に修飾してください – quamrana

答えて

5

operator<<文字列と文字を出力するオーバーロードはフリー機能です。しかし、メンバー関数を呼び出すときは、ostreamで宣言されたメンバー関数の1つの候補に強制的に変換します。 '*'の場合は、おそらくintのオーバーロードが使用され、"foo"の場合は、おそらくconst void*のオーバーロードが使用されます。

私はostreamを継承しませんが、代わりにostreamを参照メンバーとして格納してからoperator<<に委譲します。また、operator<<をメンバーにするのではなく、無料の関数テンプレートにすることはできません。また、特殊化するのではなく、std::stringchar const*の両方にoperator<<をオーバーロードします。

2

次のような何かがうまくいくかもしれない:

#include <ostream> 
#include <string> 

using namespace std; 

class MyStream: public ostream 
{ 
public: 
    MyStream(ostream& out): ostream(out.rdbuf()) {} 

    template <typename T> MyStream& operator<<(const T& value) 
    { 
     (ostream&)*this << '+' << value << '+'; 
     return *this; 
    } 
    MyStream& operator<< (const string& value) 
    { 
     (ostream&)*this << '*' << value << '*'; 
     return *this; 
    } 
    MyStream& operator<< (const char* cstr) 
    { 
     (ostream&)*this << '(' << cstr << ')'; 
     return *this; 
    } 
}; 
+0

私は今削除した私の投稿にコメントしてくれてありがとう - 私は今OPの要点を得ています。 – quamrana

+0

quamranaさんの質問にあなたのコメントが書かれています。なぜ、「なぜostreamが受け入れられるMyStreamを置き換えたいのですか」と聞いたところです。継承はここに商品を与えません。それは単にいくつかの危険をもたらします。 'ostream'のいろいろな' operator << 'は非仮想的なものなので、' oStream& 'が必要な場所に' MyStream'を渡すと、 'MyStream'の目的を損なうでしょう。私が意味していたのは 'operator' 'like like 'テンプレート MyStream&operator <<(MyStream&、T const&);'です。 –

関連する問題