如何将文件流作为类成员

时间:2014-07-15 20:52:24

标签: c++ io stream iostream

我有以下可在Visual C ++中使用的解析器类

class Parser
{
   private:
   const char* filename;
   std::ifstream filestream;
   std::vector<std::string> tokens;
   unsigned int linect;

   public:
   Parser(const char* filename);
   bool readline();
   std::string getstrtoken(unsigned int i) const { return tokens[i]; }
   int getinttoken(unsigned int i) const { return atoi(tokens[i].c_str()); }
};

Parser::Parser(const char* filename) :
   filename(filename),
   linect(0)
{
   filestream = ifstream(filename); // OK in VC++, not with GCC?
}

bool Parser::readline()
{
   std::string line;
   getline(filestream, line);
   std::stringstream ss(line);
   std::string token;

   tokens.clear();
   while(getline(ss, token, ' ')){ if(token != "") tokens.push_back(token); }
   linect++;
   return (filestream != NULL);
}

但是当我尝试使用GCC 4.8.2编译它时,我收到的错误是我无法分配给filestream。根据我在本网站其他地方阅读的内容,您可以

std::ifstream filestream(filename);

但你做不到

std::ifstream filestream;
filestream = ifstream(filename);

如果我想将filestream声明为Parser类的成员并在构造函数中初始化它,那么本质上就是我需要做的。

我希望将文件流保存在Parser类中,以便使用解析器的人不需要声明并跟踪它。在我看来,这应该是Parser类中的自包含,因为它的内部方法(例如readline())是唯一使用它的方法。

有没有办法实现这个适用于两个平台?

感谢。

修改:我的解决方法是明确调用open()的{​​{1}}方法。我的解析器类构造函数现在看起来像:

ifstream

3 个答案:

答案 0 :(得分:2)

您不能,因为std::ifstream已删除了复制构造函数和副本分配。您可以通过

来解决
filestream.swap(ifstream(filename)).

它在visual studio上编译的事实主要是因为它被内联到移动赋值或移动构造函数中(我不太好告诉你究竟是哪一个)。如果你试试

std::ifstream myF;
filestream = myF;

它不会编译。

但是你可以尝试做我写的那一步,或者你可以打电话给.openhttp://en.cppreference.com/w/cpp/io/basic_ifstream/open

答案 1 :(得分:1)

std :: ifstream 没有复制构造函数,可能是VC ++的众多扩展之一。正确的代码是:

Parser::Parser(const char* filename) :
   filename(filename),
   linect(0),
   filestream(filename)
{
}

请注意成员变量和参数文件名。使用 this-&gt; 或更改名称(推荐,通常前缀用于成员变量_m_

答案 2 :(得分:1)

我认为更好的解决方案是:

  1. 首先构建ifstream
  2. 使用Parser对象构建ifstream
  3. 更改Parser以存储对istream对象的引用。这使您可以灵活地解析文件,标准输入和字符串的内容。
  4. class Parser
    {
       private:
          std::istream& str;
          std::vector<std::string> tokens;
          unsigned int linect;
    
       public:
          Parser(std::istream& s) : str(s) ... {}
    
          ...
    };