Передача istream в функцию

Я делаю игровую программу, похожую на идею покемонов. У нас есть турнирный класс, который отслеживает несколько команд (своего собственного класса), который состоит из домашних животных (своего собственного класса) с разными видами домашних животных, которые являются подклассами CPet.

Мы пытаемся передать имя файла в main, от main передать это имя файла в класс Tournament. В классе Турнир мы открываем файл с:

 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, который выглядит следующим образом:

     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 }

и мы получаем ошибку:

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, чтобы проверить, правильно ли я это делал или нет.

Заранее спасибо.

3

Решение

Вам нужно передать поток по ссылке, потому что потоки обычно не копируются:

void CTeam::ParseTeam(std::istream &in)
11

Другие решения

Как уже указывал @dasblinkenlight, вам нужно / нужно передавать потоки по ссылке.

Это только верхушка айсберга. Ваш код имеет ряд более пагубных проблем. Главным среди них является такой код:

while(!(inFile.eof()))

Код как это не работает. Это не сработает. Этого никогда не было и не будет (если не считать какого-то крупного чуда). Практически невозможно поместить условие внутри цикла (с помощью оператора break), чтобы выйти из цикла в нужное время — но вы этого не сделали, и почти никто другой этого не делает, а когда вы это делаете, вы можете а также превратить сам цикл в while (true)потому что так будет всегда Другой логика, которая выходит из цикла в нужное время — потому что это условие цикла не может и не будет. [Я не хочу звучать там резко или противно, просто пытаюсь быть совершенно ясным, что этот код абсолютно не Работа.]

У вас снова та же основная проблема:

 while(!(in.eof())&&(readline != " " || readline != "/n"))

Это добавляет то, что, я думаю, является еще одной (хотя и менее распространенной и гораздо проще исправить) проблемой — ваша "/n" почти наверняка был предназначен "\n",

В большинстве случаев, что вы действительно хотите / нужно сделать, это прочитать что-то из потока, и иметь функцию, которая делает чтение, возвращающее ссылку на поток. Это позволит вам читать элементы до тех пор, пока не произойдет сбой чтения (в этот момент должен быть установлен бит сбоя потока). Как только вы это сделаете, вы можете сделать цикл условным для успешного чтения. В самый случаях удобно назвать эту функцию operator>>поэтому при чтении объекта вашего класса используется тот же синтаксис, что и при чтении объектов типа int.

Например, давайте посмотрим на ваш parseTeam:

 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);
}
}

Если бы это зависело от меня, я бы написал что-то вроде этого:

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 будет иметь что-то по этой общей линии:

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

По вопросам рекламы [email protected]