数据的共享和保护以及多态性.docx
《数据的共享和保护以及多态性.docx》由会员分享,可在线阅读,更多相关《数据的共享和保护以及多态性.docx(14页珍藏版)》请在冰豆网上搜索。
![数据的共享和保护以及多态性.docx](https://file1.bdocx.com/fileroot1/2023-1/7/3dfa82eb-fba4-4a29-8905-e8c4642e6452/3dfa82eb-fba4-4a29-8905-e8c4642e64521.gif)
数据的共享和保护以及多态性
武汉科技大学
C++上机实验报告
实验名称:
实验四
数据的共享和保护以及多态性
专业班级:
姓名:
学号:
20130413
一、实验目的
1.学习数据的共享和保护。
2.学习使用虚函数实现动态多态性。
二、实验内容
1.声明一个Dog类,自行分析设计出其可以拥有的静态数据成员和静态成员函数,设计完整程序并测试这个类,请分析写出静态数据成员和静态成员函数的功能和用法。
2.声明类X、Y、Z。
实现:
Y的成员函数可以访问X的私有数据成员,Z的成员函数可以访问X的数据成员。
用多文件结构实现以上功能。
(各类中的数据成员和函数成员请自行思考设计)
3.声明一个Vehicle(车)基类,有Run、Stop等成员函数,由此派生出bicycle(自行车)类和motorcar(汽车)类,从bicycle类和motorcar类派生出motorcycle(摩托车)类,它们都有Run、Stop等成员函数。
实现并测试这些类,注意虚基类和虚函数的使用。
4.对people类重载“==”运算符和“=”运算符,“==”运算符判断两个people类对象的id属性的大小;“=”运算符实现people类对象的赋值操作。
附:
people类的属性:
number(编号)、sex(性别)、birthday(出生日期)、id(身份证号)等等。
其中“出生日期”声明为一个“日期”类内嵌子对象。
三、实验注意事项
程序中,需要编写一个可执行函数与main主调函数,自主设计输入、输出值,使得结果可以由控制台显示输出。
四、实验程序代码
(一)Dog类
#include
#include
usingnamespacestd;
classDog
{
public:
Dog()//默认构造函数
{
weight=0;
age=0;
name="";
}
voidload(stringna,intag,floatwgh)//录入函数
{
weight=wgh;
age=ag;
name=na;
}
voidshow()
{
cout<<"***************\n狗名字:
"<"<"<}
staticintget_amount()//返回狗的数目,静态成员amount
{
returnamount;
}
staticvoidadd_anmout()//调用静态成员amount,狗的数目+1
{
amount++;
}
~Dog(){}//析构函数
private:
floatweight;
intage;
stringname;
staticintamount;
};
intDog:
:
amount=0;
Dogd[2];//定义3只狗
intadd()
{
floatweight;
intage;
stringname;
cout<<"********************\n请输入狗的名字:
"<cin>>name;
cout<<"请输入狗的年龄:
"<cin>>age;
cout<<"请输入狗的体重重:
"<cin>>weight;
d[Dog:
:
get_amount()].load(name,age,weight);
Dog:
:
add_anmout();
return0;
}
intmain()
{
while(Dog:
:
get_amount()<2)
{
add();
d[Dog:
:
get_amount()-1].show();//此时狗的数目已加,要显示上一只信息需-1
}
cout<<"*********\n狗的总数:
"<:
get_amount()<return0;
}
(二)XYZ的私有成员访问
头文件中:
classX
{
public:
X(inta=0){x=a;}//内联函数应该写在头文件里
~X(){}
friendclassY;//友元类,Y可以访问X的私有数据成员
friendclassZ;//友元函数,Z中只有Zget_x()函数可以访问X私有成员
intXget_x(){returnx;}
private:
intx;
};
classY
{
public:
Y(){}
~Y(){}
intYget_x(constX&yx){returnyx.x;}//应该养成常引用的习惯
};
classZ
{
public:
Z(){}
~Z(){}
intZget_x(X&zx){returnzx.x;}//友元函数成员
};
//由于都是内联函数,故未使用源文件实现函数功能和部分分配空间的变量的初始化;
主函数源文件:
#include
#include"XYZ.h"//自定义头文件最好用“”书写方式
usingnamespacestd;
intmain()
{
XA
(1);
YB;
ZC;
cout<<"X类对象A中的私有成员\nx="<return0;
}
(三)虚基类和虚函数的使用
#include
usingnamespacestd;
classvehicle
{
public:
vehicle(floats):
speed(s){}
virtualvoidRun()
{
cout<<"车启动"<}
virtualvoidStop()
{
cout<<"车已停"<}
~vehicle(){}
protected:
floatspeed;
};
classbicycle:
virtualpublicvehicle
{
public:
bicycle(floats,floatw):
vehicle(s),weight(w){}
voidRun()
{
cout<<"***********\n自行车速度:
"<"<}
voidStop()
{
cout<<"自行车已停"<}
~bicycle(){}
protected:
floatweight;
};
classmotorcar:
virtualpublicvehicle
{
public:
motorcar(floats,intn):
vehicle(s),seatamount(n){}
voidRun()
{
cout<<"***********\n汽车速度:
"<"<}
voidStop()
{
cout<<"汽车已停"<}
~motorcar(){}
protected:
intseatamount;
};
classmotorcycle:
publicbicycle,publicmotorcar
{
public:
motorcycle(floats,floatw,intn):
vehicle(s),bicycle(s,w),motorcar(s,n){}
voidRun()
{
cout<<"***********\n摩托车速度:
"<"<"<}
voidStop()
{
cout<<"摩托车已停"<}
~motorcycle(){}
};
intmain()
{
vehiclea(15.5);
bicycleb(15.5,10.5);
motorcarc(60,4);
motorcycled(30.5,200,2);
vehicle*p[4]={&a,&b,&c,&d};
for(inti=0;i<4;i++)
{
p[i]->Run();
p[i]->Stop();
}
return0;
}
(四)People类,运算符重载
#include
#include
usingnamespacestd;
enumSEX{man,woman};//性别属性为枚举类型
classDate
{
public:
Date(unsignedintdy,unsignedintmon,unsignedintyr)//内联构造函数
{
day=dy;
month=mon;
year=yr;
}
Date()//默认构造函数
{
day=0;
month=0;
year=0;
}
Date(Date&d)
{
day=d.day;
month=d.month;
year=d.year;
}
voidoperator=(Dated){
day=d.day;
month=d.month;
year=d.year;
}
intshow(void)//内联成员函数
{
cout<return0;
}
~Date(){}//析构函数
private:
unsignedintday,month,year;
};
classPeople
{
public:
People(stringna,stringnum,SEXsx,Datebirth,charid_num[19]);//构造函数
People(){}
People(People&p);
intshow(void);
voidoperator=(People&p);//复制构造函数的功能一样,实现类的复制,且设为常成员函数,避免改变参数
intoperator==(People&p);
voidshow_name(){cout<~People(){}
private:
stringname,number;//类的数据成员
char*id;
Datebirthday;//内嵌对象生日
SEXsex;//性别
};
People:
:
People(stringna,stringnum,SEXsx,Datebirth,charid_num[19]):
birthday(birth)//组合类构造函数
{
name=na;
number=num;
sex=sx;
id=id_num;
birthday=birth;
}
People:
:
People(People&p):
birthday(p.birthday)//组合类复制构造函数
{
name=p.name;
number=p.number;
sex=p.sex;
id=p.id;
}
voidPeople:
:
operator=(People&p)//运算符重载的实现,同复制构造函数
{
name=p.name;
number=p.number;
sex=p.sex;
id=p.id;
birthday=p.birthday;
}
intPeople:
:
operator==(People&p)
{
if(strcmp(id,p.id)>0)return0;
if(strcmp(id,p.id)==0)return1;
if(strcmp(id,p.id)<0)return2;
}
intPeople:
:
show(void)
{
stringtemp;
if(sex==man)temp="男";
elsetemp="女";
cout<<"************************\n姓名:
"<"<"<";
birthday.show();
cout<<"身份证号:
"<return0;
}
intmain(void)
{Datebirthday1(1,1,1995);
Peoplep1("A","001",man,birthday1,"4201061995907361x");p1.show();
Peoplep2("B","002",man,birthday1,"42010619959073610");p2.show();
Peoplep3;
p3=p2;
p3.show();
switch(p3==p1)
{
case0:
p3.show_name();cout<<"的编号较大"<case1:
cout<<"两者编号一样大"<case2:
p1.show_name();cout<<"的编号较大"<}
return0;}
五、实验运行结果
(一)Dog类
(二)XYZ的私有成员访问
(三)虚基类和虚函数的实现
(四)People类和运算符的重载
六、实验心得与体会
本次试验所获颇多,很多收获都写在了程序的注释里,比如内联函数最好放在头文件里,方便声明,而在声明时内存会分配空间的变量或函数不能在,头文件里声明,以免在多个源文件里调用头文件时,一个变量或函数分配多个空间,造成连接错误,虚基类和虚函数在引用时的对应关系,隐藏规则等等等等,这里不再一一列举。
在完成第四题的过程中,由于对运算符重载的错误理解,导致return空的类,而卡在这个BUG上好久。
用与复制构造函数一样的引用方法解决之后,身心为之畅然。
总之,这次试验让我理解到了C++抽象类对象的强大之处。
C++是一门更加符合人类思维逻辑的语言,在以后的学习中,我努力学习,掌握好这门强大的语言。