Redirecting std::cout

前端 未结 1 693
我在风中等你
我在风中等你 2021-02-18 14:38

I need a class that redirects one ostream to another ostream during the lifetime of its object. After some tinkering I came up with this:

#include 

        
1条回答
  •  时光说笑
    2021-02-18 15:26

    The reason those lines are the same is because what you're doing is swapping the buffers. (That is, you "redirect" by swapping the original buffer with the redirect buffer; restoration is the swap back.)

    While this might give you the intended effect with respect to the output stream, it's not correct because the redirect stream now outputs somewhere else. To redirect means to take one stream and make it output somewhere else; note this doesn't effect that 'somewhere else'.

    Your class is not a redirect; as is, it should really be named ScopedStreamSwap. For example, try this instead:

    #include 
    #include 
    
    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
    }
    

    What you want is this:

    #include 
    #include 
    
    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;
    }
    

    0 讨论(0)
提交回复
热议问题