2011-01-20 7 views
20

オブジェクトの存続期間中にostreamを別のostreamにリダイレクトするクラスが必要です。いくつかの微妙な調整の後、私はこれを思いついた。std :: coutをリダイレクトする

#include <iostream> 
#include <fstream> 


class ScopedRedirect 
{ 
public: 
    ScopedRedirect(std::ostream & inOriginal, std::ostream & inRedirect) : 
     mOriginal(inOriginal), 
     mRedirect(inRedirect) 
    { 
     mOriginal.rdbuf(mRedirect.rdbuf(mOriginal.rdbuf())); 
    } 

    ~ScopedRedirect() 
    { 
     mOriginal.rdbuf(mRedirect.rdbuf(mOriginal.rdbuf())); 
    }  

private: 
    ScopedRedirect(const ScopedRedirect&); 
    ScopedRedirect& operator=(const ScopedRedirect&); 

    std::ostream & mOriginal; 
    std::ostream & mRedirect; 
}; 


int main() 
{ 
    std::cout << "Before redirect." << std::endl; 
    std::ofstream filestream("redirected.txt"); 
    { 
     ScopedRedirect redirect(std::cout, filestream); 
     std::cout << "During redirect." << std::endl; 
    } 
    std::cout << "After redirect." << std::endl; 

    return 0; 
} 

うまくいくようだ。しかし、それは次の行が両方コンストラクタとデストラクタで繰り返されることを奇妙だ:

mOriginal.rdbuf(mRedirect.rdbuf(mOriginal.rdbuf())); 

私はそれが正しいことだと思うが、私はSOのコミュニティで検証したいと思います。このコードでエラーや危険を見つけることができますか?

編集

コピー不可。

+4

1 - それは正しいはずです - しかし、あなたは、一般的な面であなたのロジックを実装している場合、それは良いだろう'std :: cout'を直接呼び出すのではなく、' std :: ostream'を実行します。 –

+1

@Billy ONeal:ScopedRedirectは一般的なostreamに関してすでに実装されていませんか? std :: coutはサンプルでのみ使用されます。 – StackedCrooked

+0

私はあなたのクラスが悪いまたは間違っていると言っているわけではありません。私はちょうどあなたがそれが事実の後ろにどこにリダイレクトするよりも実際に行きたい出力に出力を送る方が良いだろうと言っています。つまり、私はstd :: coutに依存するコードは、特定の場所を指すのではなく、どこの場所を変更するかをリファクタリングする必要があると言っています。 –

答えて

17

これらの行が同じ理由は、がバッファーを交換するであるためです。 (元のバッファをリダイレクトバッファでスワップすることによって "リダイレクト"されます;復元はスワップバックです)

出力ストリームに対して意図した効果が得られるかもしれませんが、リダイレクトストリームは他の場所に出力されます。 リダイレクトには、1つのストリームを取り出して別のストリームに出力することを意味します。これは「他のどこか」には影響しないことに注意してください。

あなたのクラスはリダイレクトではありません。それは実際にはScopedStreamSwapという名前にする必要があります。たとえば、代わりにこれを試してみてください。

#include <iostream> 
#include <fstream> 

class ScopedRedirect 
{ 
public: 
    ScopedRedirect(std::ostream & inOriginal, std::ostream & inRedirect) : 
     mOriginal(inOriginal), 
     mRedirect(inRedirect) 
    { 
     mOriginal.rdbuf(mRedirect.rdbuf(mOriginal.rdbuf())); 
    } 

    ~ScopedRedirect() 
    { 
     mOriginal.rdbuf(mRedirect.rdbuf(mOriginal.rdbuf())); 
    }  

private: 
    ScopedRedirect(const ScopedRedirect&); 
    ScopedRedirect& operator=(const ScopedRedirect&); 

    std::ostream & mOriginal; 
    std::ostream & mRedirect; 
}; 


int main() 
{ 
    std::cout << "Before redirect." << std::endl; 
    std::ofstream filestream("redirected.txt"); 
    { 
     ScopedRedirect redirect(std::cout, filestream); 
     std::cout << "During redirect." << std::endl; 

     // oops: 
     filestream << "also to the file, right?...nope" << std::endl; 
     filestream << "ah, why am i on the screen?!" << std::endl; 
    } 
    std::cout << "After redirect." << std::endl; 

    // in main, return 0 is implicit, if there is no return statement; 
    // helpful to keep in mind in snippets and short things 
} 

は何がしたいことはこれです:

#include <iostream> 
#include <fstream> 

class ScopedRedirect 
{ 
public: 
    ScopedRedirect(std::ostream & inOriginal, std::ostream & inRedirect) : 
     mOriginal(inOriginal), 
     mOldBuffer(inOriginal.rdbuf(inRedirect.rdbuf())) 
    { } 

    ~ScopedRedirect() 
    { 
     mOriginal.rdbuf(mOldBuffer); 
    }  

private: 
    ScopedRedirect(const ScopedRedirect&); 
    ScopedRedirect& operator=(const ScopedRedirect&); 

    std::ostream & mOriginal; 
    std::streambuf * mOldBuffer; 
}; 


int main() 
{ 
    std::cout << "Before redirect." << std::endl; 
    std::ofstream filestream("redirected.txt"); 
    { 
     ScopedRedirect redirect(std::cout, filestream); 
     std::cout << "During redirect." << std::endl; 

     // yay: 
     filestream << "also to the file, right?...yes" << std::endl; 
     filestream << "i am not on the screen" << std::endl; 
    } 
    std::cout << "After redirect." << std::endl; 

    return 0; 
} 
+2

+1。 –

+0

作業用の修正を投稿していただきありがとうございます。私はバッファーを交換していたことに気がつきましたが、私は変なことをすることができませんでした。何らかの理由で構文が私に多く混乱します。 – StackedCrooked

関連する問題