1
class user
{
private:
    std::string  first_name;
    std::string middle_name;
    std::string  last_name;
     int ID;
     static int next_id;

public:

         static int next_user_id()
        {
        next_id++;
        return next_id;
        }
        group User_Group;   
        void set_ID(int c)
        {
        ID=c;
        }
        int get_ID()
        {
        return ID;
        }
        void set_first_name(std::string c)
        {
            first_name=c;
        }
        string get_first_name()
        {
        return first_name;
        }
        void set_middle_name(std::string c)
        {
            middle_name=c;
        }
        string get_middle_name()
        {
            return middle_name;
        }
        void set_last_name(std::string c)
        {
            last_name=c;
        }
        string get_last_name()
        {
             return last_name;
        }
        user()
        {
            ID = user::next_id++;
        }
friend istream operator>>(istream is, user User);
friend ostream operator<<(ostream os, user User);
};
int user::next_id;
istream operator>>(istream is, user User)
{
    is >> User.get_first_name();
    is >> User.get_middle_name();
    is >> User.get_last_name();
    is >> User.get_ID();
    is >> User.User_Group.get_name();
    for(int j=0;j<=4;j++)
    {
        is >> User.User_Group.Week_Food[j].get_breakfsat();
        is >> User.User_Group.Week_Food[j].get_lunch();
        is >> User.User_Group.Week_Food[j].get_dinner();
    }
    for (int j=0;j<=30;j++) 
    {
        is >> User.User_Group.Month_Food[j].get_breakfsat();
        is >> User.User_Group.Month_Food[j].get_lunch();
        is >> User.User_Group.Month_Food[j].get_dinner();
    }
}


ostream operator<<(ostream os, user User)
{
    os<<User.get_first_name()<<" "<< User.get_middle_name() <<" "<<User.get_last_name()<<" ";
        for(int j=0;j<=4;j++)
        {
        os<<User.User_Group.Week_Food[j].get_breakfsat()<<" "<<User.User_Group.Week_Food[j].get_lunch()<<" "<< User.User_Group.Week_Food[j].get_dinner()<<" ";
        }
        for (int j=0;j<=30;j++) 
        {
        os<< User.User_Group.Month_Food[j].get_breakfsat()<<" "<<User.User_Group.Month_Food[j].get_lunch()<<" "<<User.User_Group.Month_Food[j].get_dinner();
        }
}

私はC ++を初めて使用し、これはばかげた質問かもしれませんが、オブジェクトの配列をファイルに書き込み、<<および>>演算子をオーバーロードしてそこから読み取る必要があります。int と bool のクラスのメンバーに使用しようとすると、エラーが発生します。文字列型ではうまくいくように見えるので、どうすればいいのかわかりません。

4

3 に答える 3

4

問題の 1 つがここにあります。

is >> User.get_ID();

get_ID()intby 値を返します。値を変数に「ストリーミング」するには、値へのID(非定数) 参照を返す必要があります。

class user {
  ....
  int& get_ID() { return ID; }  // non-const version (e.g. for istream)
  const int& get_ID() { return ID; } // const version
  ...
 };

さらに、ストリームへの参照を取得して返す演算子が必要です。

friend istream& operator>>(istream& is, user User);
friend ostream& operator<<(ostream& os, user User);

User参照を渡すことでオブジェクトのコピーを避けることもできます:

friend istream& operator>>(istream& is, user& User); // modifies user so no const
friend ostream& operator<<(ostream& os, const user& User); // should not modify user

これには、 getter メソッドを作成する必要がconstありますが、とにかく実行する必要があります。

于 2013-01-13T17:00:37.377 に答える
0

コードがコンパイルに失敗する理由は、コンパイラが許可していない一時ファイルを読み込んでいるためです。ポイントは、への呼び出しがユーザー構造体の値のコピーget_ID()(!) を返すことです。その後、そのコピーに何らかの値を保存すると、元のものが変更されないままになります。デフォルトでは、関数に渡され、関数から返されるすべてのパラメーターがコピーされることに注意してください。

これを修正するには、is >> User.get_ID()useを使用する代わりにis >> User.ID. 出力についても同様に行いますが、問題はありません。operator>>operator<<はフレンド関数であるため、これらのプライベート変数にアクセスできます。

于 2013-01-13T17:57:13.140 に答える
0

リーダー関数には、次のような行があります。

is >> User.get_first_name();
is >> User.get_middle_name();
is >> User.get_last_name();
is >> User.get_ID();

これらの関数は、書き込み可能なものではなく、読み取り可能な左辺値または値を返します。次のように、これらの関数のオーバーロードを追加できます。

int & get_ID() // Note return of reference to member variable!
{
return ID;
}

しかし、今持っている getter を const にする必要があります (オブジェクトをクエリするため、変更しないでください):

int get_ID() const // <- note const - meaning this fn doesn't change user.
{
return ID;
}

これは、戻り値の型だけではオーバーロードを区別できないためです。ゲッターを const にすることで、暗黙の this 引数を const& にします。

そうは言っても、参照を返すオーバーロードは追加しません。メンバー変数を潜在的に有害な方法で公開するため、これは悪い習慣です。istream からローカル変数に読み取ってから、セッターを使用することをお勧めします。それが彼らの目的です。

int myID;
is >> myID;
set_ID(myID);

これにより、次の可能性が開かれます。

  1. あなたのセッターは、あなたのクラスオブジェクトに直接読み込むことによって短絡された入力をチェックインすることができます.

  2. 入力ストリームからの読み取り後にエラーが発生しなかったことを確認するチェックを追加できます。

これにより、柔軟性が得られます。不正なファイルやデータベースから身を守ることが常に最善であることがわかりました。

于 2013-01-13T17:45:46.213 に答える