我想创建一个自定义输入文件流,自动去除评论和其他垃圾数据。我提出了以下解决方案:
class FileReader : public std::ifstream
{
public:
explicit FileReader(const char* fName) { open(fName); }
~FileReader() { if (is_open()) close(); }
template <typename T, bool IsBaseOfSerializable>
struct DoRead
{
void operator()(std::ifstream& ifs, T& data) { ifs >> data; }
};
template <typename T>
struct DoRead<T, true>
{
void operator()(FileReader& reader, T& data) { data.Deserialize(reader); }
};
template <typename T>
friend FileReader& operator>>(FileReader& reader, T& data)
{
reader.SkipCommentsAndGarbage();
DoRead<T, std::is_base_of<ISerializable, T>::value> doread;
doread(reader, data);
return reader;
}
void SkipCommentsAndGarbage() {... }
};
我还有接口(interface) ISerializable
包含 Serialize/Deserialize
方法。我觉得一切都很好。
但我读到我永远不应该继承 std::ifstream
并且应该创建自定义 std::streambuf
。
你能解释一下为什么从 std::ifstream
继承是不好的吗?我如何创建自定义的 std::streambuf
来忽略注释和类似的其他数据怎么办?
最佳答案
我不清楚您希望您的类(class)如何运作。这
operator>>
函数在 std::istream
中不是虚函数,并且
迟早(通常更快,在编写良好的代码中),你会
以 std::istream&
结尾。你是转发的想法可以
在某些情况下使用,但在这种情况下,您不会继承自
std::ifstream
;你包含一个指向 istream
的指针,并且
转发给它。 (通过不继承,你确保你不能
以 istream&
结尾。这是有限的,但可以接受
某些情况。)
通常的做法是提供一个过滤
streambuf,过滤输入文本。例如,如果
注释是从 #
到行尾,而你不需要
不得不担心报价之类的,像
以下将起作用:
class UncommentStreambuf : public std::streambuf
{
std::streambuf* mySource;
std::istream* myOwner;
char myBuffer;
protected:
int underflow() override
{
int results = mySource->sbumpc();
if ( results == '#' ) {
while ( mySource->sgetc() != '\n' ) {
mySource->sbumpc();
}
}
if (results != traits_type::eof()) {
myBuffer = results;
setg( &myBuffer, &myBuffer, &myBuffer + 1 );
} else {
setg( nullptr, nullptr, nullptr );
}
return results;
}
public:
UncommentStreambuf( std::streambuf* source )
: mySource( source )
, myOwner( nullptr )
{
}
UncommentStreambuf( std::istream& source )
: mySource( source.rdbuf() )
, myOwner( &source )
{
source.rdbuf( this );
}
~UncommentStreambuf()
{
if ( myOwner != nullptr ) {
myOwner->rdbuf( mySource );
}
}
};
如果你需要处理其他类型的评论,或者担心 引用注释字符,你需要更多的逻辑(可能 一个用于收集字符的专用缓冲区,以便测试 一个以上字符的序列)。
关于c++ - 为什么不继承ifstream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23270176/