问题:考虑14章的编程练习5中的类定义。完成下面的任务。
编写一个程序,他使用标准C++ I/O 、文件I/O 以及14章的编程练习5中定义的employee、manager、fink和highfink类型的数据。
该程序应包含程序清单17.17中的代码行,即允许用户将新数据添加到文件中。改程序首次被运行时,将要求用户输入数据,然后显示所有的数据,并将这些信息保存到文件中。当改程序再次被运行时,将首先读取并显示文件中的数据,然后让用户添加数据,并显示所有的数据。
差别之一是,应通过一个指向employee类型的指针数组来处理数据。这样指针可以指向employee对象,也可以指向从employee 派生出来的其他三种对象中的任何一种。使数组较小有助于检查程序, 例如, 您可能将数组限定为最多包含10个元素:
const int MAX = 10; //no more than 10 objects
……
employee* pc[MAX];
为通过键盘输入,程序应使用一个菜单,让用户选择要创建的对象类型。菜单项使用一个switch,以便使用new 来创建指定类型的对象, 并将它的地址赋给pc数组中的一个指针。然后改对象可以使用虚函数setall()来提示用户输入相应的数据:
pc[i]->setall(); //invokes function corresponding to type of object
为将数据保存到文件中,应设计一个虚函数writeall();
for(int i = 0; i< index; i++)
pc[i]->wirteall(fout); //fout ofsteam connected to output file
注意:对于这个联系,应使用文本I/O , 而不是二进制 I/O(遗憾的是,徐对象包含指向虚函数指针表的指针,而write()将把这种信息复制到文件中。使用read()读取文件额内容,以填充对象时,函数指针值将为乱码, 这将扰乱虚函数的行为)。可使用换行符将字段分隔开,这样在输入时将很容易识别各个字段。也可以使用二进制I/O , 但不能将对象作为一个整体写入, 而应该提供分别对每个类成员应用write() 和 read()的类方法。这样,程序将只把所需的数据保存到文件中。
比较难处理的部分是使用文件恢复数据,问题在于:程序如何才能知道接下来要恢复的项目是employee对象、manager对象、fink对象还是highfink对象?一种方法是,在对象的数据写入文件时,在数据前面加上一个指示对象类型的整数。这样,在文件输入时,程序便可以读取该整数,并使用switch语句创建一个适当的对象来接收数据:
enum classkind{Employee, Manager, Fink, HighFink};
...
int classtype;
while((fin>> classtype).get(ch))
{
switch(classtye)
{
case Employee:
pc[i] = new employee();
break;
}
}
然后便可以使用指针调用虚函数getall()来读取信息:
pc[i] -> getall();
---------------------------------------------------------------------------------------------------------------------
以下为简单的类实现, 并没有实现题目的所有要求。
abstr_emp.h
#ifndef ABSTR_EMP_H
#define ABSTR_EMP_H
#include <iostream>
#include <string>
enum classKind{ Abstr_emp, Employee, Manager, Fink, Highfink };
class abstr_emp
{
public:
abstr_emp();
abstr_emp(const std::string& fn, const std::string & ln, const std::string &j);
virtual ~abstr_emp() = 0;
public:
virtual void ShowAll() const;
virtual void SetAll();
protected:
int m_iClassType;
virtual void Data() const;
virtual std::ostream& writeData(std::ostream& os);
virtual std::istream& readData(std::istream& os);
public:
virtual std::ostream& writeALL(std::ostream& os);
virtual std::istream& readALL(std::istream& os);
friend std::ostream& operator<<(std::ostream& os, const abstr_emp& e)
{
os << e.strFirstName << " " << e.strLastName << std::endl;
return os;
}
private:
std::string strFirstName;
std::string strLastName;
std::string strJob;
};
class employee : public abstr_emp
{
public:
employee();
employee(const std::string& fn, const std::string & ln, const std::string &j);
~employee();
public:
virtual void ShowAll() const;
virtual void SetAll();
protected:
virtual void Data() const;
virtual std::ostream& writeData(std::ostream& os);
virtual std::istream& readData(std::istream& os);
public:
virtual std::ostream& writeALL(std::ostream& os);
virtual std::istream& readALL(std::istream& os);
};
class manager : virtual public abstr_emp
{
public:
manager();
manager(const std::string& fn, const std::string& ln, const std::string & j, int ico = 0);
manager(const abstr_emp& e, int ico);
manager(const manager& m);
~manager();
public:
virtual void ShowAll() const;
virtual void SetAll();
protected:
virtual void Data() const;
virtual std::ostream& writeData(std::ostream& os);
virtual std::istream& readData(std::istream& os);
public:
virtual std::ostream& writeALL(std::ostream& os);
virtual std::istream& readALL(std::istream& os);
private:
int inchargeof;
protected:
int InChargeOf() const { return inchargeof; }
int& InChargeOf() { return inchargeof; }
};
class fink : virtual public abstr_emp
{
public:
fink();
fink(const std::string& fn, const std::string& ln,
const std::string &j, const std::string &rpo);
fink(const abstr_emp& e, const std::string & rpo);
fink(const fink& e);
~fink();
public:
virtual void ShowAll() const;
virtual void SetAll();
public:
virtual std::ostream& writeALL(std::ostream& os);
virtual std::istream& readALL(std::istream& os);
protected:
virtual void Data() const;
virtual std::ostream& writeData(std::ostream& os);
virtual std::istream& readData(std::istream& os);
private:
std::string strReportsto;
protected:
const std::string ReportsTo() const { return strReportsto; }
std::string & ReportsTo() { return strReportsto; }
};
class highfink : public manager, public fink
{
public:
highfink();
highfink(const std::string& fn, const std::string & ln,
const std::string & j, const std::string& rpo, int ico);
highfink(const abstr_emp& e, const std::string & rpo, int ico);
highfink(const fink& f, int ico);
highfink(const manager& m, const std::string & rpo);
highfink(const highfink & h);
~highfink();
public:
virtual void ShowAll() const;
virtual void SetAll();
public:
virtual std::ostream& writeALL(std::ostream& os);
virtual std::istream& readALL(std::istream& os);
protected:
virtual void Data() const;
virtual std::ostream& writeData(std::ostream& os);
virtual std::istream& readData(std::istream& os);
};
#endif
abstr_emp.cpp
#include "stdafx.h"
#include "abstr_emp.h"
abstr_emp::abstr_emp()
{
printf("abstr_emp create.\n");
}
abstr_emp::abstr_emp(const std::string& fn, const std::string & ln, const std::string &j)
:strFirstName(fn),
strLastName(ln),
strJob(j)
{
printf("abstr_emp create, first name = %s, last name = %s, job = %s .\n",fn.c_str(), ln.c_str(), j.c_str());
}
abstr_emp::~abstr_emp()
{
printf("abstr_emp destroy.\n");
}
void abstr_emp::ShowAll() const
{
printf("abstr_emp ShowAll, call data() function.\n");
Data();
}
void abstr_emp::SetAll()
{
printf("abstr_emp SetAll.\n");
}
void abstr_emp::Data() const
{
printf("abstr_emp Data, first name = %s, last name = %s, job = %s.\n", strFirstName.c_str(), strLastName.c_str(), strJob.c_str());
}
std::ostream& abstr_emp::writeData(std::ostream& os)
{
os << Abstr_emp << std::endl;
os << strFirstName << std::endl;
os << strLastName << std::endl;
os << strJob << std::endl;
return os;
}
std::istream& abstr_emp::readData(std::istream& os)
{
os >> m_iClassType;
if (m_iClassType == Abstr_emp)
{
os >> strFirstName;
os >> strLastName;
os >> strJob;
//std::getline(os, strFirstName);
//std::getline(os, strLastName);
//std::getline(os, strJob);
}
return os;
}
std::ostream& abstr_emp::writeALL(std::ostream& os)
{
return writeData(os);
}
std::istream& abstr_emp::readALL(std::istream& os)
{
return readData(os);;
}
employee::employee() :abstr_emp()
{
printf("employee create.\n");
}
employee::employee(const std::string& fn, const std::string & ln, const std::string &j)
:abstr_emp( fn, ln, j)
{
printf("employee create, first name = %s, last name = %s, job = %s .\n", fn.c_str(), ln.c_str(), j.c_str());
}
employee::~employee()
{
printf("employee destroy.\n");
}
void employee::ShowAll() const
{
printf("employee ShowAll. \n");
abstr_emp::Data();
Data();
}
void employee::SetAll()
{
printf("employee SetAll.\n");
abstr_emp::SetAll();
}
void employee::Data() const
{
printf("employee Data.\n");
}
std::ostream& employee::writeData(std::ostream& os)
{
os << Employee << std::endl;
return os;
}
std::istream& employee::readData(std::istream& os)
{
os >> m_iClassType;
return os;
}
std::ostream& employee::writeALL(std::ostream& os)
{
writeData(os);
return abstr_emp::writeData(os);
}
std::istream& employee::readALL(std::istream& os)
{
readData(os);
if (m_iClassType == Employee)
{
abstr_emp::readData(os);
}
return os;
}
manager::manager() :abstr_emp()
{
printf("manager create.\n");
}
manager::manager(const std::string& fn, const std::string& ln, const std::string & j, int ico /*= 0*/)
: abstr_emp(fn, ln, j),
inchargeof(ico)
{
printf("manager create, first name = %s, last name = %s, job = %s , inchargeof = %d.\n", fn.c_str(), ln.c_str(), j.c_str(), ico);
}
manager::manager(const abstr_emp& e, int ico)
:abstr_emp(e),
inchargeof(ico)
{
printf("manager create with const abstr_emp .\n");
}
manager::manager(const manager& m)
:abstr_emp(m)
{
printf("manager const manager&.\n");
if (this != &m)
{
inchargeof = m.inchargeof;
}
}
manager::~manager()
{
printf("manager destroy.\n");
}
void manager::ShowAll() const
{
printf("manager ShowAll. inchargeof = %d\n", inchargeof);
abstr_emp::Data();
Data();
}
void manager::SetAll()
{
printf("manager SetAll.\n");
abstr_emp::SetAll();
}
void manager::Data() const
{
printf("manager Data. inchargeof = %d\n", inchargeof);
}
std::ostream& manager::writeData(std::ostream& os)
{
os << Manager << std::endl;
os << inchargeof << std::endl;
return os;
}
std::istream& manager::readData(std::istream& os)
{
os >> m_iClassType;
if (m_iClassType == Manager)
{
os >> inchargeof;
}
return os;
}
std::ostream& manager::writeALL(std::ostream& os)
{
writeData(os);
return abstr_emp::writeALL(os);
}
std::istream& manager::readALL(std::istream& os)
{
readData(os);
if (m_iClassType == Manager)
{
abstr_emp::readData(os);
}
return os;
}
fink::fink()
:abstr_emp()
{
printf("fink create.\n");
}
fink::fink(const std::string& fn, const std::string& ln, const std::string &j, const std::string &rpo)
: abstr_emp(fn, ln, j),
strReportsto(rpo)
{
printf("fink create, first name = %s, last name = %s, job = %s , rpo = %s.\n", fn.c_str(), ln.c_str(), j.c_str(), rpo.c_str());
}
fink::fink(const abstr_emp& e, const std::string & rpo)
:abstr_emp(e),
strReportsto(rpo)
{
printf("fink create with abstr_emp.\n");
}
fink::fink(const fink& e)
:abstr_emp(e)
{
printf("fink create with const fink.\n");
if (this != &e)
{
strReportsto = e.strReportsto;
}
}
fink::~fink()
{
printf("fink destroy.\n");
}
void fink::ShowAll() const
{
printf("fink ShowAll. reportsto %s\n", strReportsto.c_str());
abstr_emp::Data();
Data();
}
void fink::SetAll()
{
printf("fink SetAll.\n");
abstr_emp::SetAll();
}
void fink::Data() const
{
printf("fink Data, reportsto = %s.\n", strReportsto.c_str());
}
std::ostream& fink::writeData(std::ostream& os)
{
os << Fink << std::endl;
os << strReportsto << std::endl;
return os;
}
std::istream& fink::readData(std::istream& os)
{
os >> m_iClassType;
if (m_iClassType == Fink)
{
os >> strReportsto;
}
return os;
}
std::istream& fink::readALL(std::istream& os)
{
readData(os);
if (m_iClassType == Fink)
{
abstr_emp::readData(os);
}
return os;
}
std::ostream& fink::writeALL(std::ostream& os)
{
writeData(os);
abstr_emp::writeData(os);
return os;
}
highfink::highfink()
:manager(),
fink()
{
printf("highfink create with manager , fink.\n");
}
highfink::highfink(const std::string& fn, const std::string & ln, const std::string & j, const std::string& rpo, int ico)
:manager(fn, ln, j, ico),
fink(fn,ln,j, rpo)
{
printf("highfink create, first name = %s, last name = %s, job = %s , rpo = %s, ico = %d.\n", fn.c_str(), ln.c_str(), j.c_str(), rpo.c_str(), ico);
}
highfink::highfink(const abstr_emp& e, const std::string & rpo, int ico)
:manager(e, ico),
fink(e,rpo)
{
printf("highfink create with manager , fink. rpo=%s, ico = %d\n", rpo.c_str(), ico);
}
highfink::highfink(const highfink & h)
:manager(h),
fink(h)
{
if (this != &h)
{
}
}
highfink::highfink(const manager& m, const std::string & rpo)
:abstr_emp(m),
manager(m),
fink(m, rpo)
{
printf("highfink create with manager and rpo.\n");
}
highfink::~highfink()
{
printf("highfink destroy.\n");
}
void highfink::ShowAll() const
{
printf("highfink ShowAll.\n ");
abstr_emp::Data();
Data();
}
void highfink::SetAll()
{
printf("highfink SetAll.\n ");
manager::SetAll();
fink::SetAll();
}
std::ostream& highfink::writeALL(std::ostream& os)
{
writeData(os);
manager::writeData(os);
fink::writeData(os);
abstr_emp::writeData(os);
return os;
}
std::istream& highfink::readALL(std::istream& os)
{
readData(os);
if (m_iClassType == Highfink)
{
manager::readData(os);
fink::readData(os);
abstr_emp::readData(os);
}
return os;
}
void highfink::Data() const
{
manager::Data();
fink::Data();
}
std::ostream& highfink::writeData(std::ostream& os)
{
os << Highfink << std::endl;
return os;
}
std::istream& highfink::readData(std::istream& os)
{
os >> m_iClassType;
return os;
}
测试代码:
#include <iostream>
#include "abstr_emp.h"
#define WRITE_DATA
int _tmain(int argc, _TCHAR* argv[])
{
using namespace std;
std::string strFileName("temp_highfink.txt");
#ifdef WRITE_DATA
employee temp_employee("em_first", "em_last", "em_job");
manager temp_manager("ma_firest", "ma_last", "ma_job", 5);
fink temp_fink("fin_first", "fink_last", "fink_job", "fink_reporto");
highfink temp_highfink(temp_manager, "highfink_reporto");
abstr_emp* pTempObj = &temp_highfink;
ofstream ofS(strFileName.c_str(), ios_base::app);
if (ofS.is_open())
{
pTempObj->writeALL(ofS);
ofS.clear();
ofS.close();
}
else
{
cout << "create file empLoyee.txt failed.\n";
}
#else
ifstream ifS;
ifS.open(strFileName.c_str(), ios_base::in);
if (ifS.is_open())
{
char chType;
chType = ifS.peek();
int iType = chType - 48;
abstr_emp* pTempObj = NULL;
//{ Abstr_emp, Employee, Manager, Fink, Highfink };
switch (iType)
{
case Employee:
pTempObj = new employee();
break;
case Manager:
pTempObj = new manager();
break;
case Fink:
pTempObj = new fink();
break;
case Highfink:
pTempObj = new highfink();
break;
default:
break;
}
if (pTempObj)
{
pTempObj->readALL(ifS);
pTempObj->ShowAll();
delete pTempObj;
pTempObj = NULL;
}
}
#endif
return 0;
}