首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将istream传递给函数

将istream传递给函数
EN

Stack Overflow用户
提问于 2013-01-27 23:37:41
回答 2查看 10.5K关注 0票数 4

我正在制作一个类似于精灵宝可梦的游戏类型的程序。我们有一个跟踪几支球队的锦标赛类(它自己的类),它由宠物(它自己的类)组成,不同种类的宠物是CPet的子类。

我们正在尝试将一个文件名传递给main,从main将该文件名传递给锦标赛类。在锦标赛类中,我们使用以下命令打开文件:

代码语言:javascript
复制
 14 //Construct a tournament
 15 CTournament::CTournament(const char *Filename){
 16         //opening file
 17         ifstream inFile(Filename, ios::in);
 18         if(inFile.bad()){
 19                 cout << "File error" << endl;
 20                 return ;
 21         }
 22          //get Teamlist for tournament
 23          while(!(inFile.eof())){
 24                  CTeam* temp = new CTeam;
 25                  temp->ParseTeam(inFile);
 26 
 27                  TeamList.push_back(temp);
 28          }
 29 }

这里我们将inFile传入CTeam.ParseTeam,如下所示:

代码语言:javascript
复制
     30 void CTeam::ParseTeam(std::istream in){
     31   string readline;
     32   getline(in, readline);
     33   this->TeamName = readline;
     34   while(!(in.eof())&&(readline != " " || readline != "/n"))
     35   {
     36           getline(in, readline);
     37           this->Parse(readline);
     38   }
     39 }

我们得到了错误:

代码语言:javascript
复制
In file included from /usr/include/c++/4.4/ios:39,
                 from /usr/include/c++/4.4/ostream:40,
                 from /usr/include/c++/4.4/iostream:40,
                 from CTournament.h:11,
                 from CTournament.cpp:8:
/usr/include/c++/4.4/bits/ios_base.h: In copy constructor 'std::basic_ios<char, std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)':
/usr/include/c++/4.4/bits/ios_base.h:790: error: 'std::ios_base::ios_base(const std::ios_base&)' is private
/usr/include/c++/4.4/iosfwd:47: error: within this context
/usr/include/c++/4.4/iosfwd: In copy constructor 'std::basic_istream<char, std::char_traits<char> >::basic_istream(const std::basic_istream<char, std::char_traits<char> >&)':
/usr/include/c++/4.4/iosfwd:53: note: synthesized method 'std::basic_ios<char, std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)' first required here 
CTournament.cpp: In constructor 'CTournament::CTournament(const char*)':
CTournament.cpp:25: note: synthesized method 'std::basic_istream<char, std::char_traits<char> >::basic_istream(const std::basic_istream<char, std::char_traits<char> >&)' first required here 
CTournament.cpp:25: error:   initializing argument 1 of 'void CTeam::ParseTeam(std::istream)'

我知道有一个类似的问题,他没有包括fstream。我们在两个头文件中都包含了它。

我认为这可能是没有将正确的类型传递到PraseTeam中的问题,但我找不到任何关于如何将文件传递到ParseTeam中以验证我是否正确操作的非常具体的东西。

提前谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-01-27 23:41:22

您需要通过引用传递流,因为流通常是不可复制的:

代码语言:javascript
复制
void CTeam::ParseTeam(std::istream &in)
票数 14
EN

Stack Overflow用户

发布于 2013-01-28 00:19:35

正如@dasblinkenlight已经指出的,你需要/想要通过引用来传递流。

不过,这只是冰山一角。您的代码有许多更有害的问题。其中最主要的代码如下:

代码语言:javascript
复制
while(!(inFile.eof()))

像这样的代码已经崩溃了。恐怕行不通。它从来没有,也永远不会(除非出现一些重大的奇迹)。在循环中加入一个条件(使用break语句)以在正确的时间退出循环几乎是不可能的--但是您还没有这样做,而且几乎没有人这样做,而且当您这样做时,您可能会把循环本身变成while (true),因为在正确的时间退出循环的总是其他逻辑--因为这个循环条件不能也不会。我并不想在这里听起来很苛刻或令人讨厌,只是想完全清楚这段代码绝对不能工作。

你在这里又遇到了同样的基本问题:

代码语言:javascript
复制
 while(!(in.eof())&&(readline != " " || readline != "/n"))

这增加了我猜测的另一个问题(虽然不太常见,也更容易修复) --您的"/n"几乎肯定是"\n"

在大多数情况下,您真正想要/需要做的是从流中读取一些内容,并让执行读取操作的函数返回对流的引用。这将允许您读取项目,直到读取失败(此时应设置流的失败位)。一旦你这样做了,你就可以使循环以读取成功为条件。在大多数情况下,将该函数命名为operator>>比较方便,因此读取类的对象与读取int之类的内容使用相同的语法。

例如,让我们看一下您的parseTeam

代码语言:javascript
复制
 void CTeam::ParseTeam(std::istream in){
   string readline;
   getline(in, readline);
   this->TeamName = readline;
   while(!(in.eof())&&(readline != " " || readline != "/n"))
   {
           getline(in, readline);
           this->Parse(readline);
   }
 }

如果由我来决定,我会写更多这样的东西:

代码语言:javascript
复制
std::istream &operator>>(std::istream &is, CTeam &t) { 
     std::getline(is, t.Teamname);
     CTeam::member member;
     while (is >> member)
         t.members.push_back(member);
     return is;
}

然后,CTeam将会有一些大致的东西:

代码语言:javascript
复制
class CTeam {
    // ...
public:
    class member { 
        // ...     
        friend std::istream &operator>>(std::istream &is, member &m) { 
            // code to read one team member from is
        }
    };
};

我还应该补充说,如果不了解更多关于该计划的信息,该组织肯定不是具体的--例如,不清楚我所展示的CTeam::member实体是否真的能够存在于团队的上下文之外。如果它可以,那么您(几乎可以肯定)希望使它成为CTeam之外的一个独立类。目前,我只是在猜测如何根据我从您发布的代码中收集到的信息来组织代码。

摘要:任何形式的while (!whatever.eof())都会不可挽回地损坏。您几乎总是希望使用while (read_something())。C++中的约定是使用>>从流中读取项。在可能的情况下/如果可能,遵循该约定。哦,是的,您几乎总是希望通过引用来传递流(唯一的例外是您需要使用指向流的指针--这种情况很少见,但它确实时不时地发生)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14548962

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档