我需要一个类在其对象的生命周期内将一个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)
| 归档时间: |
|
| 查看次数: |
6012 次 |
| 最近记录: |