Сохранение типа класса объекта в файл и его чтение в C ++

Моя программа состоит в том, что у меня есть класс Abstract Employee, который имеет 3 наследующих подкласса: Manager, Researcher и Engineer.

Все 3 имеют 3 общих данных, а затем свои собственные данные для хранения.

Эти 3 класса должны быть сохранены через вектор указателей на класс Employee, а затем приведен к понижению для каждого элемента.

Наконец, у него есть функции сохранения и загрузки из файла.

Я могу делать все остальное, кроме загрузки данных обратно. Проблема в том, что в начале кода, как мне определить, что каждый элемент вектора относится к определенному унаследованному классу; например: vec [0] - менеджер, vex [1] - инженер и т. д.

Вот весь мой код. Код проблемы, который я пробовал, находится в void MenuControl () Switch Case 5.

#ifndef EMPLOYEE_H
#define EMPLOYEE_H

#include<iostream>
#include <string>
#include <fstream>

using namespace std;

class Employee
{
    public:
        Employee();
        virtual void BasicInfo()=0;
        virtual void DisplayInfo()=0;
        virtual void SaveInfo(ofstream& outFile)=0;
        virtual void LoadInfo(ifstream& inFile)=0;
        ~Employee();
    protected:
        string f_Name, l_Name;
        int salary;
};


Employee::Employee(){}
Employee::~Employee(){}

void Employee::BasicInfo()
{

}

void Employee::DisplayInfo()
{

}
#endif
#ifndef MANAGER_H
#define MANAGER_H


#include<iostream>
#include <string>
#include <fstream>
#include "Employee.h"
using namespace std;

class Manager : public Employee
{
    public:
        Manager();
        Manager(string fName, string lName, int sal);
        void BasicInfo();
        void DisplayInfo();
        void SaveInfo(ofstream& outFile);
        void LoadInfo(ifstream& inFile);
        ~Manager();
    protected:
        int vacation, meets;
};
#endif


//Manager::Manager(string fName, string lName, int sal) : Employee(f_Name, l_Name, salary){}
Manager::Manager(){}
Manager::Manager(string fName, string lName, int sal)
{
    f_Name = fName;
    l_Name = lName;
    salary = sal;
}

void Manager::BasicInfo()
{
    cout<<endl<<"Enter Number of Vacations: ";
    cin>>vacation;
    cout<<endl<<"Enter Number of Meetings: ";
    cin>>meets;
}

void Manager::DisplayInfo()
{
    cout<<endl<<endl<<"TYPE: Manager";
    cout<<endl<<"Name: "<<f_Name<<" "<<l_Name;
    cout<<endl<<"Salary: "<<salary<<endl;
    cout<<"Number of Vacations: "<<vacation;
    cout<<endl<<"Meetings per Week: "<<meets;
    cout<<endl<<endl<<endl;
}

Manager::~Manager()
{

}

void Manager::SaveInfo(ofstream& outFile)
{
    outFile.write((char*)&f_Name, sizeof(string));
    outFile.write((char*)&l_Name, sizeof(string));
    outFile.write((char*)&salary, sizeof(int));
    outFile.write((char*)&vacation, sizeof(int));
    outFile.write((char*)&meets, sizeof(int));
}

void Manager::LoadInfo(ifstream& inFile)
{
    inFile.read((char*)&f_Name, sizeof(string));
    inFile.read((char*)&l_Name, sizeof(string));
    inFile.read((char*)&salary, sizeof(int));
    inFile.read((char*)&vacation, sizeof(int));
    inFile.read((char*)&meets, sizeof(int));
}
#ifndef RESEARCHER_H
#define RESEARCHER_H


#include <iostream>
#include <string>
#include <fstream>
#include "Employee.h"
using namespace std;
class Researcher : public Employee
{
    public:
        Researcher();
        Researcher(string fName, string lName, int sal);
        void BasicInfo();
        void DisplayInfo();
        void SaveInfo(ofstream& outFile);
        void LoadInfo(ifstream& inFile);
        ~Researcher();
    protected:
        string TopicPhd, SchoolPhd;
};
#endif
Researcher::Researcher(){}
Researcher::Researcher(string fName, string lName, int sal)
{
    f_Name = fName;
    l_Name = lName;
    salary = sal;
}

void Researcher::BasicInfo()
{
    cout<<endl<<"Topic of PhD: ";
    cin>>TopicPhd;
    cout<<endl<<"School of PhD: ";
    cin>>SchoolPhd;
}

void Researcher::DisplayInfo()
{
    cout<<"RESEARCHER";
    cout<<endl<<"Name: "<<f_Name<<" "<<l_Name;
    cout<<endl<<"Salary: "<<salary<<endl;
    cout<<"PhD: "<<TopicPhd<<"\nSchool: "<<SchoolPhd;
    cout<<endl<<endl;
}

void Researcher::SaveInfo(ofstream& outFile)
{
    outFile.write((char*)&f_Name, sizeof(string));
    outFile.write((char*)&l_Name, sizeof(string));
    outFile.write((char*)&salary, sizeof(int));
    outFile.write((char*)&TopicPhd, sizeof(string));
    outFile.write((char*)&SchoolPhd, sizeof(string));
}

void Researcher::LoadInfo(ifstream& inFile)
{
    inFile.read((char*)&f_Name, sizeof(string));
    inFile.read((char*)&l_Name, sizeof(string));
    inFile.read((char*)&salary, sizeof(int));
    inFile.read((char*)&TopicPhd, sizeof(string));
    inFile.read((char*)&SchoolPhd, sizeof(string));
}
#ifndef ENGINEER_H
#define ENGINEER_H


#include <iostream>
#include <string>
#include <fstream>
#include "Employee.h"
using namespace std;

class Engineer : public Employee
{
    public:
        Engineer();
        Engineer(string fName, string lName, int sal);
    //  void BasicInfo(bool knowCPP, int experience, string type);
        void BasicInfo();
        void DisplayInfo();
        void SaveInfo(ofstream& outFile);
        void LoadInfo(ifstream& inFile);
        ~Engineer();
    protected:
        bool isknowingCPP;
        int exp;
        string typeOfEng;
};
#endif
Engineer::Engineer(){}
Engineer::Engineer(string fName, string lName, int sal)
{
    f_Name = fName;
    l_Name = lName;
    salary = sal;
}

void Engineer::BasicInfo()
{
    cout<<endl<<"Knows C++(0/1): ";
    cin>>isknowingCPP;
    cout<<endl<<"Years of Experience: ";
    cin>>exp;
    cout<<endl<<"Field of Engineering: ";
    cin>>typeOfEng;
}

void Engineer::DisplayInfo()
{
    cout<<"TYPE: Engineer";
    cout<<endl<<"Name: "<<f_Name<<" "<<l_Name;
    cout<<endl<<"Salary: "<<salary<<endl;
    cout<<"Knows C++: "<<isknowingCPP;
    cout<<endl<<"Experience: "<<exp;
    cout<<endl<<"Engineering: "<<typeOfEng;
    cout<<endl<<endl;
}

Engineer::~Engineer()
{

}

void Engineer::SaveInfo(ofstream& outFile)
{
    outFile.write((char*)&f_Name, sizeof(string));
    outFile.write((char*)&l_Name, sizeof(string));
    outFile.write((char*)&salary, sizeof(int));
    outFile.write((char*)&isknowingCPP, sizeof(bool));
    outFile.write((char*)&exp, sizeof(int));
    outFile.write((char*)&typeOfEng, sizeof(string));
    /*outFile<<"Engineer";
    outFile<<endl<<"FirstName: "<<f_Name;
    outFile<<endl<<"LastName: "<<l_Name;
    outFile<<endl<<"Salary: "<<salary;
    outFile<<endl<<"Knows C++: "<<isknowingCPP;
    outFile<<endl<<"Experience: "<<exp;
    outFile<<endl<<"Engineering: "<<typeOfEng;
    outFile<<endl<<endl;*/
}

void Engineer::LoadInfo(ifstream& inFile)
{
    inFile.read((char*)&f_Name, sizeof(string));
    inFile.read((char*)&l_Name, sizeof(string));
    inFile.read((char*)&salary, sizeof(int));
    inFile.read((char*)&isknowingCPP, sizeof(bool));
    inFile.read((char*)&exp, sizeof(int));
    inFile.read((char*)&typeOfEng, sizeof(string));
}
#include <iostream>
#include <string>
#include <vector>

#include "Engineer.h"
#include "Manager.h"
#include "Researcher.h"

using namespace std;

void MenuControl(int id);
void AddEmployee(int type);
void DeleteEmployee(int id);
int empStrength;
bool quit = false;
vector<Employee*> emps;
int main()
{
    /*Manager* man = new Manager("Shash", "Sharma", 30);
    emps.push_back(man);
    emps[0]->BasicInfo();*/
    int optionID;
    //delete emps[0];
    while(!quit)
    {
        cout<<endl<<"1) Add Employee \n2) Delete Employee \n3)Display List \n4)Save Data \n5)Load Data \nAny other number to Quit: ";
        cin>>optionID;
        MenuControl(optionID);
    }
}

void MenuControl(int id)
{
    switch(id)
    {
        case 1:
            {
                int empType;
                cout<<endl<<endl<<"Adding Employee..."<<endl;
                cout<<endl<<"Please choose Employee category: "<<endl<<"1)Manager\n2)Researcher\n3)Engineer\nAny other number to exit: ";
                cin>>empType;
                AddEmployee(empType);
                break;
            }

        case 2:
            {
                int deleteID;
                cout<<endl<<"Deleting Employee..."<<endl;
                cout<<endl<<"Enter Employee Code: ";
                cin>>deleteID;
                DeleteEmployee(deleteID);
                break;
            }

        case 3:
            {
                if(emps.size()>0)
                {
                    for(int i=0; i<emps.size(); i++)
                    {
                        emps[i]->DisplayInfo();
                    }
                }
                else
                    cout<<endl<<"No data available!"<<endl;

                break;
            }

        case 4:
            {
                if(emps.size()>0)
                {
                    ofstream outfile("EmployeeData.txt", ios_base::binary);
                    for(int i=0; i<emps.size(); i++)
                    {
                        emps[i]->SaveInfo(outfile);
                    }
                    outfile.close();


                    ofstream outfile02("Employees.dat", ios_base::binary);
                    outfile02.write((char*)&empStrength, sizeof(int));
                    cout<<endl<<"Employee Strength: "<<empStrength;
                    outfile02.close();


                    ofstream outfile03("EmployeeTypes.txt", ios_base::binary);
                    for(int i=0; i<emps.size(); i++)
                    {
                        //outfile03<<&emps[i]<<endl;
                        outfile03.write(reinterpret_cast<char*>(&emps[i]) , sizeof(Employee));
                    }
                }
                cout<<endl<<"Data Saved";
                cout<<endl<<endl;
                break;
            }

        case 5:
            {
                ifstream infile02("Employees.dat", ios_base::binary);
                infile02.read((char*)&empStrength, sizeof(int));
                cout<<endl<<"Employee Strength: "<<empStrength;
                emps.resize(empStrength);
                cout<<endl<<emps.size();

                Employee* temp;
                ifstream infile03("EmployeeTypes.txt", ios_base::binary);
    //          infile03.read(reinterpret_cast<char*>(&temp), sizeof(Employee));
                for(int i=0; i<emps.size(); i++)
                {
                    cout<<endl<<"BeforeSeg";
                    infile03.read(reinterpret_cast<char*>(temp), sizeof(Employee));
                    cout<<endl<<"SegError";
                    emps[i] = temp;
                }
                break;
            }

        default:
            {
                quit = true;
                break;
            }
    }
}

void AddEmployee(int type)
{
    string fName, lName;
    int sal;
    switch(type)
    {
        case 1:
            {
            //, holiday, meetings;
            cout<<endl<<endl<<"First Name: ";
            cin>>fName;
            cout<<endl<<"Last Name: ";
            cin>>lName;
            cout<<endl<<"Salary: ";
            cin>>sal;
            Manager* man = new Manager(fName, lName, sal);
            man->BasicInfo();
            emps.push_back(man);
            empStrength++;
            break;
            }

        case 2:
            {
            cout<<endl<<endl<<"First Name: ";
            cin>>fName;
            cout<<endl<<"Last Name: ";
            cin>>lName;
            cout<<endl<<"Salary: ";
            cin>>sal;
            Researcher* res = new Researcher(fName, lName, sal);
            res->BasicInfo();
            emps.push_back(res);
            empStrength++;
            break;
            }

        case 3:
            {
            cout<<endl<<endl<<"First Name: ";
            cin>>fName;
            cout<<endl<<"Last Name: ";
            cin>>lName;
            cout<<endl<<"Salary: ";
            cin>>sal;
            Engineer* eng = new Engineer(fName, lName, sal);
            eng->BasicInfo();
            emps.push_back(eng);
            empStrength++;
            break;
            }

        default:
            cout<<endl<<endl<<"No such Employee Type. Please put correct values"<<endl;
    }
}

void DeleteEmployee(int id)
{
    if(id<emps.size())
    {
        emps.erase(emps.begin() + id);
        empStrength--;
    }
    else
    {
        cout<<endl<<"No such ID yet."<<endl;
    }
}

Я новичок в C ++, поэтому, пожалуйста, не стесняйтесь :)


person artofshashank    schedule 27.10.2014    source источник


Ответы (1)


Один из подходов состоит в том, чтобы определить переменную типа внутри вашего класса сотрудников, затем назначить эту переменную внутри каждого производного конструктора, а затем сохранить / загрузить эту информацию.

Быстрый пример кода, иллюстрирующий то, что я предлагаю:

// inside Employee.h
enum eEmployeeTypes
{
   ET_NONE,
   ET_MANAGER,
   ET_RESEARCHER,
   ET_ENGINEER
}

class Employee
{
  ...
  protected:
  eEmployeeTypes m_Type;
}

//employee cpp
Employee::Employee()
{
  ...
  m_Type = ET_NONE
}

// Sample modified constructor for Manager
// manager.cpp
Manager::ManageR()
{
  ...
  m_Type = ET_MANAGER;
}

Теперь перейдем к сложной части, поскольку вам нужна информация во время загрузки:

Вы должны сначала сохранить информацию о типе внутри файла.

Затем вы должны создать функцию Factory для Employee, которая использует конструктор approrpriate, и прочитать что-то вроде:

static Employee* CreateEmployeeFromFile(ifstream& file)
{
    eEmployeeTypes type;
    file.read((eEmployeeTypes*)&type, sizeof(eEmployeeTypes));
    Employee* rez=null;
    if (type == ET_MANAGER)
    {
       rez = new Manager();
       rez.LoadInfo(file);
    }
    ...
    return rez;
}
person MichaelCMS    schedule 27.10.2014
comment
Хорошо, я протестирую ваш подход. Но, вместо Enum, если я просто добавлю int, относящийся к каждому типу Employee в данных, это тоже сработает? Например: я поставил Manager как 1, Researcher как 2 и так далее, а затем, читая файл во время загрузки, запустите переключатель или цикл if, как вы делаете, и создаю каждый элемент как один и тот же? В любом случае большое спасибо. Протестирую и через какое-то время одобрю ответ :) - person artofshashank; 27.10.2014
comment
На самом деле перечисления и целые числа - это одно и то же в C ++, это просто помогает вам последовательно увеличивать постоянные значения. Компиляторы могут выбрать преобразование перечисления в байтовое / короткое, поэтому при использовании перечислений безопаснее использовать перечисление sizeof вместо того, чтобы напрямую предполагать, что это int. - person MichaelCMS; 27.10.2014
comment
Ох, хорошо. Итак, сохраняя его в двоичном файле, я указываю его размер как sizeof (eEmployeeTypes)? - person artofshashank; 27.10.2014
comment
Если вы используете перечисления, да, это то, что вам нужно :). Один небольшой трюк, который вы можете сделать, - это заставить enum быть int, чтобы вы не столкнулись с ошибками позже, если вы используете другие компиляторы. Вот ссылка на трюк (второй ответ - тот, который вы ищете): stackoverflow.com/questions/4879286/ - person MichaelCMS; 27.10.2014
comment
Извините за поздний ответ. Я попытался сделать это точно так же, как и ваш, но это дало некоторые ошибки, поэтому я просто исправил ошибки, и все было хорошо! Большое спасибо за помощь! :) - person artofshashank; 03.11.2014