C++ 为什么不从ifstream继承
我想创建一个自定义的输入文件流,它可以自动删除注释和其他垃圾数据。我提出了以下解决方案:C++ 为什么不从ifstream继承,c++,stream,ifstream,streambuf,C++,Stream,Ifstream,Streambuf,我想创建一个自定义的输入文件流,它可以自动删除注释和其他垃圾数据。我提出了以下解决方案: class FileReader : public std::ifstream { public: explicit FileReader(const char* fName) { open(fName); } ~FileReader() { if (is_open()) close(); } template <typename T, bool IsBaseOfSerializabl
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() {... }
};
我还有一个接口ISerializable,其中包含序列化/反序列化方法。我觉得一切都很好
但我已经读到,我不应该从std::ifstream继承,而应该创建自定义std::streambuf
您能解释一下为什么从std::ifstream继承是不好的,我如何创建自定义std::streambuf,它以类似的方式忽略注释和其他数据?基本上是std::iostream设计来定制std::streambuf,这就是所有特定于上下文的功能所在。我不清楚您希望您的类如何工作。这个 运算符>>函数在std::istream中不是虚拟的,并且 迟早通常,在编写良好的代码中,您将 以std::istream&结束。你的想法是转发罐头 在某些情况下可以使用,但在这种情况下,您不会继承 std::ifstream;您包含指向istream的指针,并且 期待它。通过不继承,您可以确保您不能 以一个istream结束&。这是有限的,但在某些情况下是可以接受的 某些情况 通常的做法是提供一个过滤 streambuf,用于过滤输入文本。例如,如果 注释从a到行的末尾,而您没有 不得不担心引用之类的事情,比如 以下将起作用:
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 );
}
}
};
如果你需要处理其他类型的评论,或者担心
引用注释字符,您可能需要更具逻辑性
用于收集字符的专用缓冲区,用于测试
一个以上字符的序列 因为公开继承以修改ifstream的行为将导致意外的后果,因为它仍然是一个istream,在许多情况下都会被视为istream-剥离您的自定义行为: 将FileReader传递给需要::std::istream&的函数时,将不使用自定义功能 具有模板T&operator>>T&in、C&target等运算符的任何C类;将无法使用 无论何时直接使用底层istream的任何功能,包装器函数都不起作用 在您的情况下,您可以简单地切换到将ifstream作为成员,或者将其继承更改为private