实验4 面向对象的程序设计--类与对象(2学时)
一、实验目的
1.掌握C++类的概念和基本组成,学会设计类,掌握类对象的声明和使用方法;
2.熟悉各种成员函数包括构造函数、析构函数、内嵌函数的定义与使用;
3.掌握静态数据成员的使用。
二、实验内容及步骤
(一)验证实验程序
1.定义一个描述学生通讯录的类,数据成员包括:姓名、学校、电话号码和邮编;成员函数包括:
输出各个数据成员的值,分别设置和获取各个数据成员的值。
分析:由于姓名、学校和电话号码的数据长度是可变的,可使用动态的数据结构。邮编的长度是固定
的,可定义一个字符数组来存放邮编。将数据成员均定义为私有的。用一个成员函数输出所有的成员数据,
用四个成员函数分别设置姓名、单位、电话号码和邮编,再用四个成员函数分别获取姓名、单位、电话号
码和邮编。主函数完成简单的测试工作。
参考程序如下:
#include <iostream.h>
#include <string.h>
class COMMU
{ | char *pName; | //姓名,数据成员为私有的 |
char *pSchool; | //单位 | |
char *pNum; | //电话号码 | |
char Box[10]; | //邮编 |
public:
void Print(void) //输出数据成员 {
cout<<"姓名:"<<pName<<'\t';
cout<<"单位:"<<pSchool<<'\t';
cout<<"电话号码:"<<pNum<<'\t';
cout<<"邮编:"<<Box<<'\n';
}
void Init(char *,char *,char *,char *);
void FreeSpace(void); //释放数据成员占用的空间void SetName(char *name)
{
if(pName)
delete[ ] pName; //释放存储空间
pName= new char[strlen(name)+1]; //申请存储空间 strcpy(pName,name);
}
voidSetScool(char *unit) //置学校名称{
if(pSchool )
delete[] pSchool;
pSchool= new char[strlen(unit)+1];
strcpy(pSchool,unit);
}
voidSetNum(char *num) //置电话号码{
if(pNum )
delete[ ] pNum;
pNum= new char[strlen(num)+1];
strcpy(pNum,num);
}
voidSetBox(char *mailnum) //置邮编 {
strcpy(Box,mailnum);
}
char*GetName(void)
//取姓名 {
returnpName;
}
char*GetScool(void ) //取学校 {
return pSchool;
}
char*GetNum(void) //取电话号码 {
returnpNum;
}
char*GetBox(void) //取邮编 {
returnBox;
}
};
void COMMU::Init(char *name,char *unit,char *num,char *b) { //完成初始化 pName= new char [strlen(name)+1];
strcpy(pName,name);
pSchool= new char [strlen(unit)+1];
strcpy(pSchool,unit);
pNum= new char [strlen(num)+1];
strcpy(pNum,num);
strcpy(Box,b);
}
void COMMU::FreeSpace()
{
if(pName)delete [] pName;
if(pSchool)delete [] pSchool;
if(pNum) delete [] pNum;
}
voidmain( )
{
COMMU c1,c2;
c1.Init("于元","河海大学","025-85595638","210024");
c2.Init("王海","南京理工大学","025-85432455","210015");c1.Print();
c2.Print();
c1.SetName("王");
cout<<c1.GetName()<<'\n';
c1.SetScool("南京理工大学");
cout<<c1.GetScool()<<'\n';
c1.SetNum("025-88755635");
cout<<c1.GetNum()<<"\n";
c1.SetBox("210090");
cout<<c1.GetBox()<<"\n";
c1.Print();
c1.FreeSpace();
c2.FreeSpace();
}
思考:
?用以下数据测试程序的正确性:
名字改为“李明明”,并输出;
学校改为“北京理工大学”并输出;
电话改为“010—55667878”,并输出;
邮编改为“150035”并输出。
?将成员函数的权限改为私有的,观察现象。
?将类改为结构体,重新执行程序,输出成员数据。
?增加数据成员:邮件地址,手机号码,并将电话号码分为住宅电话和办公电话。
2.设计一个管理图书的简单程序,描述一本书的信息包括:书号,书名,出版社和作者等。提供的
基本功能包括:可连续将新书存入文件“book.dat”中,新书信息加入到文件的尾部;也可以根据输入的书名
进行查找;把文件“book.dat”中同书名的所有书显示出来。
分析:
可以把描述一本书的信息定义为一个Book类,它包含必要的成员函数。把加入的新书总是加入到文
件尾部,所以,以增补方式打开输出文件。从文件中查找书时,总是从文件开始位置查找,以读方式打开
文件。用一个循环语句实现可连续地将新书加入文件或从文件中查找指定的书名。由于是以一个Book类
的实例进行文件输入输出的,所以,这文件的类型应该是二进制文件。
简化的参考程序如下:
#include<iostream.h>
#include<string.h>
#include<fstream.h>
class Book
{
longint num; //书号
charbookname[40]; //书名
charpublicname[40]; //出版社
charname[20]; //作者
public:
Book(){num=0; bookname[0] =0;publicname[0] =0; name[0] =0;} char *Getbookname(void) {return bookname ;}
long Getnum(void ) { return num;}
voidSetdata(long , char *,char *,char *);
voidShow(void );
Book(long, char *,char *,char *);
};
void Book::Setdata(long nu , char *bn,char *p,char *n)
{
num= nu; strcpy(bookname,bn);
strcpy(publicname,p);strcpy(name,n);
}
void Book::Show(void )
{
cout<<"书号:"<<num<<'\t'<<"书名:"<<bookname<<'\t';
cout<<"出版社:"<<publicname<<'\t'<<"作者:"<<name<<'\n';}
Book::Book(longnu, char * bp,char *p,char *n)
{
Setdata(nu, bp, p, n);
}
void main(void)
{
Book b1,b2;
long nu;
charbn[40]; //书名
charpn[40]; //出版社
charna[20]; //作者
ifstream file1;
ofstream file3;
charflag = 'y';
while(flag=='y' ||flag=='Y') //由flag控制循环
{
cout<<"\t\t1: 按书名查找一本书!\n";
cout<<"\t\t2: 加入一本新书!\n";
cout<<"\t\t3: 退出!\n输入选择:";
intf;
cin>>f;
switch(f)
{
case1:
cout<<"输入要查找的书名:";cin>>bn;
file1.open("book.dat",ios::in| ios::binary);//按读方式打开文件while(!file1.eof())
{
intn;
file1.read((char*)&b1,sizeof(Book));
n=file1.gcount();
if(n==sizeof(Book))
{
}
}
file1.close();
break;
case 2:
cout<<"输入书号:"; cin>>nu;
cout<<"输入书名:"; cin>>bn;
cout<<"输入出版社:"; cin>>pn;
cout<<"输入作者:"; cin>>na;
b1.Setdata(nu,bn,pn,na);
file3.open("book.dat",ios::app|ios::binary);//增补方式打开文件 file3.write((char*)&b1,sizeof(b1));
file3.close();
break;
default: flag = 'n';
}
}
}
思考:修改程序增加
?按出版社、作者从文件中查找书名;
?输出同一出版社出版的所有书名;
?按列表的格式输出文件中的所有书名等功能。
3. 改正以下程序中的错误,并分析错误原因。提示:该程序中point 类的构造函数定义
不正确, 在main()中对数据成员的访问不正确。要求修改程序后,在主函数中创建一个
对象并初始化为坐标(5,5),然后输出这个点的X,Y 坐标。
(二)完成实验项目
1.声明一个Circle类,有
1)数据成员Radius(半径)
2)成员函数GetArea()计算圆的面积
3)构造函数Circle(floatradius)进行初始化
4)析构函数
在主函数中创建一个Circle类的对象进行测试(输入一个数值,作为Circle类对象的半径,调用该对象的GetArea()求以该数值为半径的圆的面积)。
2.声明一个tree类,有
1)数据成员ages(树龄)
2)成员函数grow(intyears)对ages加上years
3)成员函数age()显示对象的数据成员ages的值
4)构造函数tree(intn=0)进行初始化
5)析构函数
在主函数中创建一个tree类的对象进行测试(创建一个树龄为18的对象,
调用age()显示树龄,之后调用grow(4),生长4年,再显示树龄)。
3.人员信息管理系统:
以一个小型公司的人员管理为例,说明类及成员函数的设计。提示:
1)类的设计:
某小型公司,需要存储雇员的编号、级别、月薪,并显示全部信息。根据这些 需求,设计一个类employee,在该类中,包括的数据成员有:
编号(intindividualEmpNo)
级别(intgrade)
月薪(floataccumPay)
成员函数有:
设置编号(voidsetEmpNo(intsteps)):编号顺序加1(利用静态变量实现) 提取编号(voidgetEmpNo)
晋升级别(voidpromote(intincrement)):提升的级别由参数指定
提取级别(intgetGrade)
设置月薪(voidSetAccumPay(float pa)):
提取月薪(floatGetAccumPay)
构造函数(用于设置数据成员编号、级别和月薪初值)
析构函数
2)整个程序分为两个的文档:employee.h(包含类的定义和类的实现)和 employee.cpp(主函数文件)
3)在主函数main()中创建employee类的两个对象,对它们设计编号、级别和月 薪,并输出每个雇员的基本信息。
三、课后作业
1. 撰写实验报告