2010-11-17 28 views
0

Je pense avoir des problèmes avec le fichier binaire io. Si je cours mon programme, crée des objets d'employé et les montre alors tout fonctionne bien. Si je sauvegarde les données de l'objet et recharge le programme, je reçois une exception RTTI. Il me semble que mes fonctions LoadEmployeeData() et Savelist (vector & e) fonctionnent très bien. L'exception se produit dans ma fonction DisplayEmployeeData() lorsque j'essaie d'utiliser typeid. Pour réitérer, je reçois une erreur RTTI lors de l'utilisation de typeid sur un objet chargé depuis le disque.C++ problème avec RTTI ou fichier binaire io

//****************header file*********** 
#include <string.h> 
#include <iostream> 
#include <string> 
#include <vector> 
#include <fstream> 
#include <sstream> 
#include <typeinfo> 
#include <ctime> 
#include <cstdlib> 
using namespace std; 
class Employee 
{ 
private: 
    int employeeID; 
    char name[80]; 
    int SSN; 
public: 
    Employee(); 
    Employee(int, char*,int); 
    virtual ~Employee(); 
    virtual void DisplayBaseData(); 
    //getters 
    int GetID(); 
    char* getName(); 
    int GetSSN(); 
    //setters 
    void SetID(int); 
    void SetName(char*); 
    void SetSSN(int); 
};//end Employee class 

class Salary : public Employee 
{ 
private: 
    double salary; 
public: 

    Salary(); 
    Salary(int, char*, int, double); //id, name, ssn, salary 
    ~Salary(); 
    void DisplayEmployeeData(); 
    //getters 
    double GetSalary(); 
    //setters 
    void SetSalary(double); 
};//end class Exempt 

class Hourly : public Employee 
{ 
private: 
    double rate; 
    double hoursWorked; 
public: 
    Hourly(); 
    Hourly(int, char*, int, double, double); //id, name, ssn, rate 
    ~Hourly(); 
    void DisplayEmployeeData(); 
    //getters 
    double GetRate(); 
    double GetHoursWorked(); 
    //setters 
    void SetRate(double); 
    void SetHoursWorked(double); 
};//end Hourly Class 

    const int HOURLYTYPE = 0; 
    const int SALARYTYPE = 1; 

// * ** * ***corps* ** * ** *

#include "lab05.h"; 


Employee::Employee(){}; 
Employee::Employee(int ID, char* nme, int ssn) : employeeID(ID), SSN(ssn) 
{ 
    strcpy(name, nme); 
} 
int Employee::GetID() 
{ 
    return employeeID; 
} 
char* Employee::getName() 
{ 
    return name; 
} 
int Employee::GetSSN() 
{ 
    return SSN; 
} 
void Employee::SetID(int i) 
{ 
    employeeID = i; 
} 
void Employee::SetName(char* n) 
{ 
    strcpy(name, n); 
} 
void Employee::SetSSN(int i) 
{ 
    SSN = i; 
} 
void Employee::DisplayBaseData() 
{ 
    cout << "ID: \t" << employeeID << endl; 
    cout << "Name: \t " << name << endl; 
    cout << "SSN: \t" << SSN << endl; 
} 
Employee::~Employee(){} 


Salary::Salary(){} 
Salary::Salary(int id, char* nme, int ssn, double slry) : Employee(id, nme, ssn), salary(slry){} 
void Salary::DisplayEmployeeData() 
{ 
    DisplayBaseData(); 
    cout << "Salary: \t " << salary << endl; 
} 
double Salary::GetSalary() 
{ 
    return salary; 
} 

void Salary::SetSalary(double d) 
{ 
    salary = d; 
} 
Salary::~Salary(){} 


Hourly::Hourly(){} 
Hourly::Hourly(int id, char* nme, int ssn, double rte, double worked) : Employee(id, nme, ssn), rate(rte), hoursWorked(worked){} 
void Hourly::DisplayEmployeeData() 
{ 
    DisplayBaseData(); 
    cout << "Rate: \t" << rate << endl; 
    cout << "Worked: \t " << hoursWorked << endl; 
} 
double Hourly::GetRate() 
{ 
    return rate; 
} 
double Hourly::GetHoursWorked() 
{ 
    return hoursWorked; 
} 
void Hourly::SetRate(double d) 
{ 
    rate = d; 
} 
void Hourly::SetHoursWorked(double d) 
{ 
    hoursWorked = d; 
} 
Hourly::~Hourly(){} 




vector<Employee*> LoadEmployeeData() 
{ 

    vector<Employee*> employeeList; 
    string fileName = ""; 
    cout << "\nEnter filename for employee data: "; 
    cin >> fileName; 
    fstream file; 


    file.open(fileName, ios::in, ios::binary); 
    char buffer[4096] = {0}; 
    int numEntries; 
    file.read((char*)&numEntries, sizeof(int)); 
    cout << numEntries << " number of entries found." << endl; 
    if (numEntries != 0) 
    { 
     int identifier; 
     for (int i = 0; i < numEntries; i++) 
     { 
      file.read((char*)&identifier, sizeof(int)); 
      if (identifier == SALARYTYPE) 
      { 
       Employee* temp = new Salary(); 
       file.read((char*)temp, sizeof(Salary)); 
       employeeList.push_back(temp); 
      } 
      else if (identifier == HOURLYTYPE) 
      { 
       Employee* temp = new Hourly(); 
       file.read((char*)temp, sizeof(Hourly)); 
       employeeList.push_back(temp); 
      } 
     } 
    } 
    else cout << "No Entries found." << endl; 

    file.close(); 
    return employeeList; 
}//end LoadEmployeeData function 

void ListEmployees(vector<Employee*> &e) 
{ 
    if (e.size() != 0) 
    { 
     for (int i = 0; i < e.size(); i++) 
     { 
      if (typeid(*(e[i])) == typeid(Hourly)) 
      { 
       cout << "\n(" << i << ")" << endl; 
       dynamic_cast<Hourly*>(e[i])->DisplayEmployeeData(); 
      } 

      else if (typeid(*(e[i])) == typeid(Salary)) 
      { 
       cout << "\n(" << i << ")" << endl; 
       dynamic_cast<Salary*>(e[i])->DisplayEmployeeData(); 
      } 
     } 
    } 
    else cout << "No items in list" << endl;  
}// end ListEmployees function 

void ModifyEmployee(vector<Employee*> &e) 
{ 
    cout << "Enter employee selection." << endl; 
} 

void CreateEmployee(vector<Employee*> &e) 
{ 
    bool continueLoop = true; 
    srand(time(0)); //seed random number generator 

    cout << "\n Enter new employee information." << endl; 
    cout << "Name: "; 
    char newName[80] = {0}; 
    cin >> newName; 
    cout << "\n SSN: "; 
    int newSSN; 
    cin >> newSSN; 
    char newType = '-1'; 
    do 
    { 
     cout << "\n Is new employee paid a (s)alary or (h)ourly rate? "; 
     cin >> newType; 
     if (newType == 's' || newType == 'h') continueLoop = false; 
     else cout << "incorrect input" << endl; 
    }while (continueLoop == true); 
    if (newType == 's') 
    { 
     cout << "Enter salary amount: "; 
     double amount; 
     cin >> amount; 
     e.push_back(new Salary(rand() % 1000 + 1, newName, newSSN, amount)); 
    } 
    else if (newType == 'h') 
    { 
     cout << "Enter hourly amount: "; 
     double amount; 
     cin >> amount; 
     cout << "Enter hours worked: "; 
     double hoursWorked; 
     cin >> hoursWorked; 
     e.push_back(new Hourly(rand() % 1000 + 1, newName, newSSN, amount, hoursWorked)); 
    } 
} 

void Savelist(vector<Employee*> &e) 
{ 
    if (e.size() == 0) 
     cout << "No employees in list. Nothing done." << endl; 
    else 
    { 
     cout << "Enter save filename: "; 
     char fileName[80] = {'\0'}; 
     cin >> fileName; 
     fstream* file = new fstream(); 
     file->open(fileName, ios::out, ios::binary); 
     char buffer[80] = {'\0'}; 
     int numEntries = e.size(); 
     file->write((char*)&numEntries, sizeof(int)); //writes number of entries 

     for (int i = 0; i < e.size(); i++) 
     { 
      if (typeid(*e[i]) == typeid(Salary)) 
      { 
       int classType = SALARYTYPE; 
       file->write((char*)&classType, sizeof(int)); 
       file->write((char*)dynamic_cast<Salary*>(e[i]), sizeof(Salary)); 
      } 
      else if (typeid(*e[i]) == typeid(Hourly)) 
      { 
       int classType = HOURLYTYPE; 
       file->write((char*)&classType, sizeof(int)); 
       file->write((char*)dynamic_cast<Hourly*>(e[i]), sizeof(Salary)); 
      } 
     } 
     file->close(); 
    } 

} 

void DeleteEmployee(vector<Employee*> &e) 
{ 
    cout << "Input index number of employee to delete: "; 
    int idx = 0; 
    cin >> idx; 
    if (idx > e.size() -1) 
     cout << "invalid index number\n" << endl; 
    else 
    { 
     delete e[idx]; 
     e.erase(e.begin() + idx); //removes from list 
    } 
} 


int main() 
{ 


    const int ZERO = 0; 
    const int ONE = 1; 
    const int TWO = 2; 
    const int THREE = 3; 
    const int FOUR = 4; 
    const int FIVE = 5; 
    const int SIX = 6; 

    int exitMainLoop = false; //for flow control 
    int mainMenuChoice = -1; 
    vector<Employee*> employeeList; 
    do 
    { 
     cout << "Select from the following options." << endl; 
     cout << "(1) Load employee data file." << endl; 
     cout << "(2) View Employees." << endl; 
     cout << "(3) Modify Employee data. " << endl; 
     cout << "(4) Create new employee." << endl; 
     cout << "(5) Save list to file." << endl; 
     cout << "(6) Delete employee data. " << endl; 
     cout << "(0) Exit program." << endl; 

     //add more options 
     cout << "Enter selection: "; 
     cin >> mainMenuChoice; 
     if (cin.fail()) 
     { 
      cout << "\nInvalid selection. Try again" << endl; 
      cin.clear(); 
      string garbage = ""; 
      cin >> garbage; 
     } 
     else if (mainMenuChoice == ONE) 
      employeeList = LoadEmployeeData(); 
     else if (mainMenuChoice == TWO)   
      ListEmployees(employeeList); 
     else if (mainMenuChoice == THREE) 
      ModifyEmployee(employeeList); 
     else if (mainMenuChoice == FOUR) 
      CreateEmployee(employeeList); 
     else if (mainMenuChoice == FIVE) 
      Savelist(employeeList); 
     else if (mainMenuChoice == SIX) 
      DeleteEmployee(employeeList); 
     else if (mainMenuChoice == ZERO) 
      exitMainLoop = true; 

    }while(exitMainLoop == false); 
    system("PAUSE"); 
} 

Répondre

0

Vous pouvez » t lire/écrire des objets C++ bruts depuis/vers le disque s'ils ont vir (ou utiliser RTTI, qui nécessite des méthodes virtuelles) car il n'y a aucune garantie que l'adresse vtable de la première exécution sera écrite sur le disque, et il n'y a aucune garantie que la vtable sera au même endroit la prochaine fois que le programme sera exécuté - Par conséquent, l'adresse qui a été écrite sur le disque pointera quelque part incorrecte lors de la relecture.

0

file-> write ((char *) dynamic_cast < Toutes les heures *> (e [i]), sizeof (salaire));

semble suspect. vouliez-vous dire sizeof (horaire)?