重定向std :: cout

Sta*_*ked 21 c++

我需要一个类在其对象的生命周期内将一个ostream重定向到另一个ostream.经过一些修修补补后,我想到了这个:

#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;
}
Run Code Online (Sandbox Code Playgroud)

它似乎工作正常.然而,它的怪异的是,下面一行是在重复这两个构造函数和析构函数:

mOriginal.rdbuf(mRedirect.rdbuf(mOriginal.rdbuf()));
Run Code Online (Sandbox Code Playgroud)

我认为这是正确的,但我想与SO社区进行核实.你能在这段代码中发现任何错误或危险吗?

编辑

使不可复制.

GMa*_*ckG 17

这些行相同的原因是因为你正在做的是交换缓冲区.(也就是说,通过使用重定向缓冲区交换原始缓冲区来"重定向";恢复是交换回来.)

虽然这可能会为您提供与输出流相关的预期效果,但它不正确,因为重定向流现在输出到其他位置.要重定向手段,采取一个流,使其输出别的地方; 请注意,这不会影响"其他地方".

你的班级不是重定向; 它本应该被命名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
}
Run Code Online (Sandbox Code Playgroud)

你想要的是这个:

#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;
}
Run Code Online (Sandbox Code Playgroud)

  • +1是有趣和翔实的,以及搞笑的示例文本. (2认同)