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

问题之一在这里:

is >> User.get_ID();

get_ID()返回一个int按值。为了将值“流式传输”到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

在您的阅读器功能中,您有这样的行:

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

这是因为重载不能仅通过返回类型来区分。使 getter const 使隐式 this 参数 const&。

说了这么多,我不会添加返回引用的重载。这是不好的做法,因为它会以潜在的破坏性方式暴露您的成员变量。我建议从 istream 读取本地变量,然后使用您的设置器。这就是他们的目的。

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

这开启了以下可能性:

  1. 您的设置器可以通过直接读取您的类对象来检查您的输入短路。

  2. 您可以在从输入流中读取后添加一个检查是否存在错误。

这为您提供了灵活性。我发现最好保护自己免受格式错误的文件和数据库的侵害。

于 2013-01-13T17:45:46.213 回答
0

代码无法编译的原因是您正在读入一个临时文件,编译器不允许您这样做。关键是调用get_ID()返回用户结构中值的副本(!)。如果您随后在该副本中存储了一些值,那么无论如何它都会使原始文件保持不变。请记住,默认情况下,所有传递给函数和从函数返回的参数都会被复制。

要解决此问题,而不是使用is >> User.get_ID()use is >> User.ID。我会为输出做类似的事情,但这并不重要。您可以访问这些私有变量,因为operator>>andoperator<<是友元函数。

于 2013-01-13T17:57:13.140 回答