Jes*_*nds 3 c++ inheritance ostream
是的,我甚至不确定如何正确地制定这个; 我觉得这是一个涉及的问题.我相信有人可以帮助我.
这就是我想要做的:
有一个我可以发送东西的课程,就像这样.
icl << "Blah blah blah" << std::endl;
Run Code Online (Sandbox Code Playgroud)我希望能够继承std :: basic_ostream的.attach()类.
然后,这些类将能够以自己的方式格式化输出.有人可能会添加一个时间戳并写入日志,另一个可能会将其写入控制台,另一个可能会在游戏中显示它.
有人想让我开始朝着正确的方向前进吗?这是我几乎拥有的想法.
#include <vector>
class OutputMan {
std::vector<std::basic_ostream&> m_Streams;
public:
void attach(std::basic_ostream& os) {
m_Streams.push_back(os);
}
}
Run Code Online (Sandbox Code Playgroud)
问题1:我需要继承和覆盖发送什么
icl << "Blah!" << std::endl;
Run Code Online (Sandbox Code Playgroud)
到m_Streams中的每个流?
问题2:如何继承std :: basic_ostream并创建一个更改输出的类,例如,在其开头添加时间戳?我也希望这个类输出到一个文件.
我想我的做法有点不同.我可能已经做了一些比必要更精细的事情 - 我担心我可能会因为尝试使用新的C++ 11功能而感到沮丧.无论如何,使用代码:
#include <streambuf>
#include <fstream>
#include <vector>
#include <iostream>
#include <initializer_list>
namespace multi {
class buf: public std::streambuf {
std::vector<std::streambuf *> buffers;
public:
typedef std::char_traits<char> traits_type;
typedef traits_type::int_type int_type;
buf(std::vector<std::ofstream> &buf) {
for (std::ofstream &os : buf)
buffers.push_back(os.rdbuf());
}
void attach(std::streambuf *b) { buffers.push_back(b); }
int_type overflow(int_type c) {
bool eof = false;
for (std::streambuf *buf : buffers)
eof |= (buf -> sputc(c) == traits_type::eof());
return eof ? traits_type::eof() : c;
}
};
class stream : public std::ostream {
std::vector<std::ofstream> streams;
buf outputs;
public:
stream(std::initializer_list<std::string> names)
: streams(names.begin(), names.end()),
outputs(streams),
std::ostream(&outputs)
{ }
void attach(std::ostream &b) {
outputs.attach(b.rdbuf());
}
};
}
int main() {
multi::stream icl({"c:\\out1.txt", "c:\\out2.txt"});
icl.attach(std::cout);
icl << "Blah blah blah" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这已经接受了操纵器(它应该适用于任何操纵器,而不仅仅是std::endl).如果要写入多个文件(可以/可以作为fstream打开的东西),您可以根据需要在构造函数中指定尽可能多的名称(当然,在系统强加的范围内).喜欢的事情std::cout,并std::cerr为你不一定有一个文件名,你可以使用attach你原本打算.
我想我应该补充说,我对此并不完全满意.它会采取一些相当严重的重写做到这一点,但经过一番思考,我认为"正确"的方式很可能是对multi::stream的构造函数是不是一个可变参数模板,所以你可以这样做:multi::stream icl("c:\\out1.txt", std::cout);,它将根据其类型理清如何使用每个参数.我可能会更新这个答案,以便很快包含该功能.
至于第二个问题,我已经写了另一个涵盖基本概念的答案,但可能有点过于精细,所以你关心的部分可能会在洗牌中丢失,可以这么说 - 它有处理你并不真正关心的行长度的相当多的逻辑(但确实产生了具有指定前缀的每个输出行,如你所愿).