代码之家  ›  专栏  ›  技术社区  ›  tomocafe

如何将文件流作为类成员

  •  1
  • tomocafe  · 技术社区  · 11 年前

    我有以下在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);
    

    如果我想申报 文件流 作为 Parser 类并在构造函数中初始化它。

    我希望将文件流保存在 分析器 类,这样使用解析器的人就不需要声明和跟踪它 分析器 类,因为它的内部方法(例如。 readline() )是唯一使用它的人。

    有没有一种方法可以在两个平台上实现这一点?

    谢谢

    编辑: 我的解决方案是显式调用 open() 方法 ifstream 。我的解析器类构造函数现在看起来像:

    Parser::Parser(const char* filename) :
       filename(filename),
       linect(0)
    {
       filestream.open(filename);
       // Do some checking to make sure the file exists, etc.
    }
    
    3 回复  |  直到 11 年前
        1
  •  2
  •   Creris    11 年前

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

    filestream.swap(ifstream(filename)).
    

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

    std::ifstream myF;
    filestream = myF;
    

    它无法编译。

    然而,你可以尝试我写的动作,或者你可以打电话 .open ( http://en.cppreference.com/w/cpp/io/basic_ifstream/open )

        2
  •  2
  •   R Sahu    8 年前

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

    1. 构造一个 ifstream 第一
    2. 构造一个 Parser 使用 文件流 对象
    3. 改变 分析器 存储对 istream 对象这允许您灵活地分析文件、stdin和字符串的内容。

    class Parser
    {
       private:
          std::istream& str;
          std::vector<std::string> tokens;
          unsigned int linect;
    
       public:
          Parser(std::istream& s) : str(s) ... {}
    
          ...
    };
    
        3
  •  1
  •   NetVipeC    11 年前

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

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

    请注意成员变量和参数 文件名 使用 这-> 或更改名称(推荐,通常前缀用于成员变量 _ m_ )