4

ポケモンのアイデアに似たゲームタイプのプログラムを作っています。CPetのサブクラスであるさまざまな種類のペットを含むペット(独自のクラス)で構成されるいくつかのチーム(独自のクラス)を追跡するトーナメントクラスがあります。

メインからメインにファイル名を渡そうとしています。そのファイル名をトーナメントクラスに渡します。トーナメントクラスでは、次のファイルを開きます。

 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に渡して、正しく行っているかどうかを確認する方法について、具体的なことは何も見つかりませんでした。

前もって感謝します。

4

2 に答える 2

14

ストリームは通常コピー可能ではないため、参照によってストリームを渡す必要があります。

void CTeam::ParseTeam(std::istream &in)
于 2013-01-27T15:41:21.973 に答える
1

@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 ++の規則は>>、ストリームからアイテムを読み取るために使用することです。可能な場合/可能であれば、その規則に従ってください。ああ、そうです、ほとんどの場合、参照によってストリームを渡したいと思うでしょう(例外は、代わりにストリームへのポインターを操作する必要がある奇妙な時間です-珍しいですが、それは時々起こります)。

于 2013-01-27T16:19:35.163 に答える