重载两个 类 的提取运算符

Overloading extraction operator for two classes

在两个class中从文件中读取成员变量时是否可以编写提取运算符?第一个class是CPerson,其中包含姓名和EGN(社会安全号码),第二个class是CStudent,其中包含FN(教职工编号)和一张带有各种测试的地图(测试代码和获得积分)。目前我已经为 class CStudent 重载了一个提取运算符,这意味着我可以访问它的私有成员,但我想为 CPerson 做同样的事情,所以我不需要使用 setter 也适用于 class。

class CPerson
{
private:
    string name;
    string EGN;

public:
    CPerson(const string n, const string e)
    {
        name=n;
        EGN=e;
    }
    void setname(const string n) {name=n;}
    void setEGN(const string e) {EGN=e;}
};

class CStudent: public CPerson
{
private:
    string FN;
    map<int, int> st_tests;

public:
    CStudent(const string o, const string p, const string n):CPerson(o,p)
    {FN=n;}
    friend istream &operator>> (istream &, CStudent &);
};

istream &operator>> (istream &input, CStudent &c)
{
    string z, x, y, line;
    int d, e;

    getline(input,line);
    istringstream ln(line);
    ln >> z >> x >> c.FN;
    c.setname(z);
    c.setEGN(x);

    while(true)
    {
        ln >> d >> e;
        c.st_tests[d] = e;
        if(!ln.good())
            break;
    }
    return input;
}

class CGroup
{
private:
    string spec; //specialty
    int kurs; //course
    int grupa; //group
    vector<CStudent> students; //vector of CStudent objects

public:
    CGroup(const string filename) //constructor with name of file to be read as parameter
    {
        string a;
        int b, c;
        ifstream st;
        st.open(filename.c_str(),ios::in);
        if(!st)
        {
            cout<<"Cannot open "<<filename<<" or file does not exist."<<endl;
            exit(1);
        }
        string line;
        getline(st,line);
        istringstream group(line);
        group >> a >> b >> c;
        spec = a;
        kurs = b;
        grupa = c;
        while(!st.eof())
        {
            CStudent student;
            st >> student;
            students.push_back(student);
        }
        st.close();
    }
};

如果需要,这里是其中一个文件的内容:

KST 1 1
Ivan 9404019382 61360125 1 55 2 90 3 78 12 82 13 99 14 78 15 72
Kaloqn 9311281029 61360126 1 82 2 43 3 95 13 50
Airqn 9408132918 61360127 1 91 2 40 3 89
Mariq 9409071824 61360128 1 55 2 91 3 78 16 0
Ginka 9312198212 61360129 1 87 2 84 3 15
Leika 9405221982 61360130 1 25 2 76 3 56
Shumaher 9305119225 61360131 1 94 2 75 3 92
Onzi 9408108876 61360132 1 40 2 59 3 49

更新的运算符:

CPerson
{
    friend istream &operator>> (istream &, CPerson &);
};

istream &operator>> (istream &input, CPerson &c)
{
    input >> c.name >> c.EGN;
    return input;
}

istream &operator>> (istream &input, CStudent &c)
{
    int d, e;
    string line;
    getline(input,line);
    istringstream ln(line);
    ln >> static_cast<CPerson&>(c) >> c.FN;
    while(ln >> d >> e)
        c.st_tests[d] = e;
    return input;
}

结果:

Ivan 9404019382 61360125 1 55 2 90 3 78 12 82 13 99 14 78 15 72
Kaloqn 9311281029 61360126 1 82 2 43 3 95 12 82 13 50 14 78 15 72
Airqn 9408132918 61360127 1 91 2 40 3 89 12 82 13 99 14 78 15 72
Mariq 9409071824 61360128 1 55 2 91 3 78 12 82 13 99 14 78 15 72 16 0
Ginka 9312198212 61360129 1 87 2 84 3 15 12 82 13 99 14 78 15 72 16 0
Leika 9405221982 61360130 1 25 2 76 3 56 12 82 13 99 14 78 15 72 16 0
Shumaher 9305119225 61360131 1 94 2 75 3 92 12 82 13 99 14 78 15 72 16 0
Onzi 9408108876 61360132 1 40 2 59 3 49 12 82 13 99 14 78 15 72 16 0

您可以在 CPerson:

中阅读 nameEGN
istream &operator>> (istream &input, CPerson &c)
{
    // this is friend function, so you can access private members of CPerson
    input >> c.name >> c.EGN; // or something similar...
    return input;
}

提取到 CStudent 将首先将数据提取到 CPerson(名称和 EGN 应该是输入数据中的第一个字符串):

istream &operator>> (istream &input, CStudent &c)
{
    input >> static_cast<CPerson&>(c); // read CPerson's data first

    string line;

    if(getline(input, line))
    {
        istringstream iss(line);

        while(iss >> d >> e) // then read CStudent's special data
            c.st_tests[d] = e;
    }

    return input;
}

一些改进建议:

CStudent student; // you will need default constructor for this

while(st >> student)
    students.push_back(student); // read like this in CGroup

const& 超过 std::string。在这些参数中用const来限制自己,没有引用几乎没有用。

CGroup(string const& filename);
CPerson(string const& n, string const& e)