104303李优实验6报告最终版Word文档下载推荐.docx
《104303李优实验6报告最终版Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《104303李优实验6报告最终版Word文档下载推荐.docx(16页珍藏版)》请在冰豆网上搜索。
![104303李优实验6报告最终版Word文档下载推荐.docx](https://file1.bdocx.com/fileroot1/2023-1/2/1a12f220-d3f1-4e35-8067-2aa84a0b64ba/1a12f220-d3f1-4e35-8067-2aa84a0b64ba1.gif)
数量
微机
LenovoTinkCentre8000
1
一、实验内容
1.类Emp、Manager、Seller、Piecer和Hourer
实验题目:
编写一个工资管理系统,以雇员类为基类公有派生出经理类、销售员类、计件工类和小时工类。
经理享有固定的底薪和业绩奖励;
销售员的收入是一小部分的基础工资加上销售额的提成;
计件工的收入完全取决于其生产的工件数量;
小时工的收入以小时计算,加上按时计算的加班费。
运用积累指针显示输出各类对象的薪水值。
具体描述:
雇员类Emp作为基类,有数据成员salary(double型表示薪水),成员函数set()为成员salary赋值(参看值为600),成员函数count()为salary赋值,成员韩式get()获取成员salary的值,成员函数show()用于显示输出成员salary的值。
经理类Manager,新增成员函数count(),用于计算经理的薪水并对salary赋值,底薪8000,业绩奖励金额有用户输入(参考值为12000);
新增成员函数show()用于显示输出函数salary的值。
销售员类Seller,新增成员函数count(),用于计算销售员的薪水并对salary赋值,进本工资800,销售提成比例为6%,有哟过户输出销售额(参考值为120000);
新增成员函数show()用于显示成员salary的值。
计件工类Piecer,新增成员函数count(),用于计算计件工的薪水并对salary赋值,计件系数为40,生产产品件数由用户输入(参考值为80),新增成员函数shouw(),用于显示输出成员salary的值。
小时工类Hourer,新增成员函数count(),用于计算小时工的薪水并对salary赋值,150小时内计时系数为10,150小时为的加班计时系数为20,工作时数由用户输入(参考值为170),新增成员函数show()用于显示输出成员salary的值。
要求
●所有类定义时,数据成员为private,成员函数为public属性,各成员函数的参数请按需要自行定义。
●所有函数都要有明确的执行信息输出,例如类Emp的构造函数中应明确输出“执行类Emp的构造函数”。
●编写主函数main(),在其中编写程序,定义各类的对象,用基类指针指向它们分别操作,对各类对象的成员salary执行count()计算并赋值、执行show()对各类对象的成员salary的值输出显示。
实验题目的编程设计思想:
工资计算器,其实就是抽象出的书上例题,与实际结合就会难上一个等级,其实只要将书看懂,再将其从实际中抽象出。
题目中具体描述已经将该程序规定出大部分。
只要按着树上的语句实现就可以了。
个人觉得只要主程序时候写得够精巧够细致,整个程序就能很好的运行,因为类函数都是一个格式,不容易出错,而且基本都是固定下来了。
程序代码、显示结果:
#include<
iostream.h>
classEmp//111111*********1111
{private:
doublesalary;
public:
Emp(doublexsalary=600)
{
cout<
<
"
执行Emp的构造函数"
endl;
salary=xsalary;
}
voidset(doublexsalary)
执行Emp的set()函数,薪水赋值为"
("
salary<
)"
virtualvoidcount()
执行Emp的count()函数"
doubleget()
执行Emp的get()函数,返回薪水值"
returnsalary;
virtualvoidshow()
执行Emp的show()函数,输出薪水:
~Emp()
执行Emp的析构函数"
};
classManager:
publicEmp//22222222222222222
{public:
Manager(doublesalary=8000):
Emp(salary)
执行Manager的构造函数"
voidcount(doublexsalary)
执行类Manager的count()函数,经理业绩奖励数额:
xsalary<
set(8000+xsalary);
voidshow()
执行类Manager的show()函数,输出经理薪水:
get()<
~Manager()
执行Manager的析构函数"
classSeller:
publicEmp//3333333333333333333
Seller(doublesalary=800):
执行Seller的构造函数"
voidcount(doublexsalary=120000)
执行类Seller的count()函数,销售员销售额:
set(800+xsalary*0.06);
执行类Seller的show()函数,输出销售员薪水:
~Seller()
执行Seller的析构函数"
classPiecer:
publicEmp//44444444444444444444444444444
Piecer(doublesalary=0):
执行Piecer的构造函数"
执行类Piecer的count<
>
函数,计件工生产产品件数:
set(40*xsalary);
执行类Piecer的show<
函数,输出计件工薪水:
~Piecer()
执行Piecer的析构函数"
classHourer:
publicEmp//5555555555555555555555555555555555555555
Hourer(doublesalary=0):
执行Hourer的构造函数"
执行类Hourer的count<
函数,小时工工时数:
if(xsalary<
=150)
{
set(10*xsalary);
}
if(xsalary>
150)
set(150*10+(xsalary-150)*20);
执行类Hourer的show()函数,输出小时工薪水:
~Hourer()
执行Hourer的析构函数"
voidmain()
{
doublei,j,m,n;
Emp*pa,a;
pa=&
a;
pa->
count();
show();
Managerb,*pb;
pb=&
b;
cout<
请输入经理的业绩奖励:
;
cin>
i;
pb->
count(i);
Sellerc,*pc;
pc=&
c;
请输入销售员的销售额:
j;
pc->
count(j);
Piecerd,*pd;
pd=&
d;
请输入计件工生产产品的件数:
m;
pd->
count(m);
Hourere,*pe;
pe=&
e;
请输入小时工的工作时数:
n;
pe->
count(n);
}
结果显示:
2.类Person、Student、Graduate和GS
设计类Person表示成员,以类Person为基类公有派生出类Student和类Graduate分别表示本科生和研究生,由类Student和类Graduate公有派生出类GS表示本硕连读生,编程实现对类GS对象所有数就成员值得修改和输出显示。
设计类Person表示人员,包含name(字符数组char[21]和age(int型)两个数据成员分标表示人员姓名和年龄,有成员函数get()和geta()用于获取数据成员name和age的值,有成员函数p_set()用于修改name和age的值。
由类Person公有派生出类Student和类Graduate,分别用于表示本科生和研究生。
类Student新增数据成员xh(字符数据char[9]型)表示学号,新增成员函数s_set()用于修改数据成员id,新增成员函数s_set()用于修改数据成员id,新增成员函数getid()用于获取数据成员id的值。
由类Student和类Graduate公有派生类GS表示本硕连读生。
●所有类定义时,数据成员为private属性,成员函数为public属性,各成员函数的参数请按需要自行设计。
●所有类都要求编写构造函数和析构函数,构造函数都为有参函数且具有默认参数值,构造函数完成数据成员的初始化。
●所有函数都要有明确的执行信息输出,例如类Person的构造函数中应明确输出“执行类Person的构造函数”。
●编写主函数main(),在其中编写程序以实现对GS对象的所有数据成员值得修改和输出显示。
虚函数解决了二义性而且非常容易,本题只是简单的输入然后输出,但是我对数组的输入处理方面想了半天,后来还是在书上找到灵感,最后实现。
但是我并没有完全实现来时的要求。
老师实现效果:
我的程序效果:
string.h>
classPerson//111111*********1111111111111111111111111
{protected:
char*name;
intage;
Person(char*xname,intxage)
{cout<
执行类Person的构造函数被执行"
name=newchar[21];
//21=strlen(xname)+1
strcpy(name,xname);
age=xage;
voidp_set(char*xname,intxage)
{name=newchar[21];
age=xage;
执行类Person的成员函数p_set(),"
voidgetn()
执行Person的成员函数getn()函数,获取name值="
name<
voidgeta()
执行Person的成员函数geta()函数,获取age值="
age<
~Person()
{delete[]name;
执行类Person的析构函数"
classStudent:
virtualpublicPerson//22222222222222222222222
{protected:
char*xh;
public:
Student(char*xxname,intxxage,char*xxh):
Person(xxname,xxage)
{xh=newchar[9];
strcpy(xh,xxh);
cout<
执行类Student的构造函数被执行"
voids_set(char*xxh)
{xh=newchar[9];
cout<
执行类Student的成员函数s_set(),"
voidgetx()
{cout<
执行Student的成员函数getx()函数,获取xh值="
xh<
}
~Student()
{delete[]xh;
执行类Student的析构函数"
};
classGraduate:
virtualpublicPerson//33333333333333333333333333333333333
char*id;
Graduate(char*xxxname,intxxxage,char*xid):
Person(xxxname,xxxage)
{id=newchar[11];
strcpy(id,xid);
执行类Graduate的构造函数被执行"
voidg_set(char*xid)
{id=newchar[11];
strcpy(id,xid);
执行类Graduate的函数g_set()"
voidgetid()
{cout<
执行Graduate的成员函数getid()函数,获取xid值="
id<
~Graduate()
{delete[]id;
执行类Graduate的析构函数"
}
classGS:
publicStudent,publicGraduate//4444444444444444444444
{public:
GS(char*gname,intgage,char*gxh,char*gid):
Student(gname,gage,gxh),Graduate(gname,gage,gid),Person(gname,gage)
执行类GS的构造函数被执行"
~GS()
执行类GS的析构函数"
};
voidmain()
{charnamee[21];
intagee;
charxhh[9];
charidd[11];
GSa1("
**GT**"
3,"
2010XXXX"
"
10XXXXXXXX"
);
下面输出初始化后类GS对象的数据成员值:
a1.getn();
a1.geta();
a1.getx();
a1.getid();
下面修改类GS对象的数据成员值:
执行类Person的成员函数p_set(),修改name="
cin>
namee;
修改age="
agee;
a1.p_set(namee,agee);
修改xh="
xhh;
a1.s_set(xhh);
修改id=:
idd;
a1.g_set(idd);
二、实验体会:
实验五、六这种类的试题怎么才能在一堆数据理出他们的关系呢?
我尝试仿照书上画关系图并附上该成员需要构造的函数和要求,使程序结构一目了然,加快了编程速度。
实现了最终的效果。
关于选作,我对数组出入当时没有想起来,后来看到书可以实现输入多少都可以的数组strlen(xname)+1,这个效果更好。
我原本还想做一个检验系统,来实现对输入xh和id进行合理性检验,但是想过实验起来没有试验,时间有限也就没有去探索,希望以后有时间一定要试一试。
三、思考题:
1、请举例或结合实验,说明虚函数的工作机制。
答:
--------------------------------------------------------------------------------
voidmain()
{basemb(50,50),*mp;
dirivemc(10,20,30);
mp=&
mb;
mp->
show();
mc;
//希望分别调用基类base的show()函数和派生类dirive的show()函数
C++中可以用虚函数来解决这个问题。
虚函数定义后,就可以通过基类指针访问基类和派生类中的虚函数。
-----------------------------------------------------------------------------------------------------------------------------------------
为什么把基类中的show()函数定义为虚函数时,程序的运行结果就正确了呢?
这是因为,关键字virtual指示C++编译器,使用语句“mp->
show()”调用虚函数时,采用动态联编的方式,即在运行时确定调用哪个show()函数。
我们把使用同一种调用形式“mp->
show()”,调用同一类族中不同类的虚函数称为动态的多态性,即运行时的多态性。
可见,虚函数与派生类的结合可使C++支持运行时的多态性。
2、请举例或结合实验,说明虚函数的工作机制。
如果一个派生类是从多个基类派生出来的,而这些基类又有一个共同的基类,则在这个派生类中访问这个共同的基类中的成员时,可能会产生二义性。
-------------------------------------------------------------------------
#include<
classB{
protected:
inta;
B(){a=5;
Ba="
a<
}};
classB1:
publicB{
B1(){a=a+10;
B1a="
classB2:
B2(){a=a+20;
B2a="
classD:
publicB1,publicB2{
D(){cout<
Da="
a<
main(){Dobj;
return0;
为了解决这种二义性,使从不同的路径继承的基类的成员在内存中只拥有一个拷贝,C++引入了虚基类的概念。
------------------------------------------------------------------------------------------------------------------------------
如果将公共基类说明为虚基类。
那么,对同一个虚基类的构造函数只调用一次,
这样从不同的路径继承的虚基类的成员在内存中就只拥有一个拷贝。
从而解决了以上的二义性问题。
虚基类的初始化与一般的多重继承的初始化在语法上基本上是一样的,但有一些特殊的规定:
(1)对同一个虚基类的构造函数只调用一次,且是在第一次出现时调用;
(2)如果在虚基类中定义有带形参的构造函数,并且没有定义默认形式的构造函数,则整个继承结构中,所有直接或间接的派生类都必须在构造函数的成员初始化表中列出对虚基类构造函数的调用,以初始化在虚基类中定义的数据成员。
(3)虚基类构造函数的调用顺序:
若同一层次中同时包含虚基类和非虚基类,应先调用虚基类的构造函数,再调用非虚基类的构造函数,最后调用派生类构造函数;
对于多个虚基类,构造函数的执行顺序仍然是先左后右,自上而下;
对于非虚基类,构造函数的执行顺序仍是先左后右,自上而下;