实验四 数据的共享与保护

实验四 数据的共享与保护

一、实验目的

1.掌握类的数据共享与保护的概念和使用方法

2.学习使用类的友元、静态成员,掌握多文件结构的程序编译预处理

二、实验内容

1、设计一个Grade类,判定学生某个考试的级别,全部操作在类Grade中实现(30分)。

要求:
(1)在定义对象时指定学生姓名和分数。且姓名必须指定,分数可缺省,缺省值为0分。要求包含构造函数、复制构造函数、姓名用string类型来定义。
主函数中实例化6个学生对象的姓名和分数分别为:
 Sun l00
 Wu 90
 Jiang 52
 Zhou 0
 He 76
 Liu 88
(2) 编写一个私有成员函数getGrade(),判定学生成绩的等级(60分以下为E等,[60-70)分为D等,[70-80)为C等,[80-90)为B等,[90-100]分为A等)。
(3)编写一个常成员函数getInfo()输出结果,包含学生姓名、分数、等级。
(4)定义静态数据成员count,用于统计总的学生人数,并在主函数中输出。
(5)定义该类的友元函数compare(Grade &m,Grade &n),比较两个学生成绩的高低,输出成绩高的那个学生信息。

2、请改写课本例题4-4线段(Line类),建立工程,使用多文件的组织结构实现程序(30分)。要求:
(1)文件划分:类定义文件(.h),类实现文件(.cpp),类使用文件(,cpp,主函数文件)。
(2)每个类的设计单独放在1个(.h)文件中,工程共包括5个文件。
(3)使用条件编译指令以免文件多次包含的情况。
(4)在Dev C++或VC中建立工程:文件-新建-项-(Basic—EmptyProject—C++项目)-新建文件夹Line,项目名称为Line,将所有文件保存在名为Line的文件夹中。VC建立过程是:文件—>新建—>工程—>Win32 Console Application。

3、请使用网页工具draw.io或其它或绘制UML图的工具创建一个UML图来描述上一题目中Line类与Point类的关系。(10分)

4、定义Boat和Car两个类,二者都有weight属性,定义二者的一个友元函数getTotalWeight()计算二者重量之和。(10分)

5、定义一个日期类(Date)和一个时间类(Time)。Time类是Date类的友元。Time类中的有打印时间的成员函数void display()可以实现打印出当前的时间,例如格式为:2021年10月30日;请编写程序设计这两个类,要求创建时间对象Today,并一次输出其中的日期和时间。(20分) 参考文献:C++关于时间操作 https://www.runoob.com/cplusplus/cpp-date-time.html

三、实验步骤及结果

题目1:

解题思路:

1.分数缺省可以在构造函数中给参数默认值0

2.判断等级可以用多重if嵌套

3.常成员函数注意const

4.统计总的人数 count应该在构造函数++和析构函数中–操作

5.比较成绩高低用if语句即可,调用getInfo输出信息

程序代码:

/*
程序名:题目1.cpp
功能:设计一个Grade类,判定学生某个考试的级别,全部操作在类Grade中 实现(30分)。要求:
(1)在定义对象时指定学生姓名和分数。且姓名必须指定,分数可缺省,缺省值为0分。要求包含构造函数、复制构造函数、姓名用string类型来定义。
主函数中实例化6个学生对象的姓名和分数分别为:
Sun l00
Wu 90
Jiang 52
Zhou 0
He 76
Liu 88
(2) 编写一个私有成员函数getGrade(),判定学生成绩的等级(60分以下为E等,[60-70)分为D等,[70-80)为C等,[80-90)为B等,[90-100]分为A等)。
(3)编写一个常成员函数getInfo()输出结果,包含学生姓名、分数、等级。
(4)定义静态数据成员count,用于统计总的学生人数,并在主函数中输出。
(5)定义该类的友元函数compare(Grade &m,Grade &n),比较两个学生成绩的高低,输出成绩高的那个学生信息。
日期:2021.11.15
版本:1.0
*/
#include <iostream>
#include <string>
using namespace std;
class Grade//Grade 类定义 
{
private://私有数据成员 
	static int count;//静态数据成员声明,用于记录学生人数 
	string name;//学生姓名 
	int score;//分数 
	char grade;//等级
	void getGrade(Grade &p);//判断学生等级 
public://外部接口 
	Grade(string name,int score=0);//构造函数 分数缺省值为0 
	Grade(Grade &p);//复制构造函数
	void getInfo(Grade &p) const;
	friend void compare(Grade &m, Grade &n);//比较成绩的友元函数声明 
	static void showcount();//输出目前人数 
};
int Grade::count = 0;//静态数据成员定义和初始化,使用类名限定 
Grade::Grade(string N,int S) :score(0)//构造函数的实现
{	
    name = N;
    score = S;
	count++;
}
Grade::Grade(Grade &p)//复制构造函数的实现 
{
	name = p.name;
	score = p.score;
	count++;
}
void Grade::getGrade(Grade &p)//判断学生等级
{
	if (p.score > 0 && p.score < 60)
    	p.grade = 'E';
	else if (p.score >= 60 && p.score < 70)
        p.grade = 'D';
	else if (p.score >= 70 && p.score < 80)
        p.grade = 'C';
	else if (p.score >= 80 && p.score < 90)
		p.grade = 'B';
	else if (p.score >= 90 && p.score <= 100)
		p.grade = 'A';
}
void Grade::getInfo(Grade &p) const//常成员函数的实现 
{	
	cout << "姓名:" << p.name << endl;
	cout << "分数:" << p.score << endl;
	p.getGrade(p);
	cout << "等级:" << p.grade << endl;
}

void compare(Grade &m, Grade &n)//友元函数实现 
{	
	cout << "*******************************" <<endl;
	cout << "两个比较的学生姓名为:" << m.name << " " << n.name << endl;
	if (m.score > n.score)
	{
		cout << "成绩高的学生信息为:" << endl;
		m.getInfo(m);
	}
	else
	{
	
		cout << "成绩高的学生信息为:" << endl;
		n.getInfo(n);
   	}
}
void Grade::showcount()//输出目前人数 
{
	cout << "目前总的人数为:" << count << endl;
}

int main()
{
	Grade p1("Sun", 100);
	Grade p2("Wu", 90);
	Grade p3("Jiang", 52);
	Grade p4("Zhou");//分数缺省 默认为0 
	Grade p5("He", 76);
	Grade p6("Liu", 88);
	Grade::showcount();
	compare(p1, p2);
	compare(p2, p3);
	compare(p4, p6);
	system("pause");
	return 0;
}

运行结果截图:

图片描述

题目2:

解题思路:

1.将项目划分成三个部分:类定义文件(.h)、类实现文件(.cpp)、类的使用文件(*.cpp,主函数文件)

由于该项目有两个类 因此一共需要5个文件

2.注意编译预处理

使用条件编译指令和defined操作符来防止对类Point的重复定义

程序代码:

//文件1,Point类的定义,Point.h
#ifndef POINT_H
#define POINT_H
class Point//Point 类定义 
{
public://外部接口 
	Point(int xx=0,int yy=0){
		x=xx;
		y=yy;
	};//构造函数 
	Point(Point &p);//复制构造函数
	int getX(){return x;}
	int getY(){return y;}
private://私有数据成员 
	int x,y;
};
#endif
//文件2,Point类的实现,Point.cpp
#include "Point.h" 
#include <iostream>
using namespace std;
Point::Point(Point &p){//复制构造函数的实现 
	x=p.x;
	y=p.y;
	cout << "Calling the copy constructor of Point" << endl;
} 
//文件3,Line类的定义,Line.h
#include "Point.h"
#ifndef LINE_H
#define LINE_H
class Line{//Line 类定义 
public://外部接口 
	Line(Point xp1,Point xp2);//构造函数 
	Line(Line &l);//复制构造函数 
	double getLen(){return len;}
private://私有数据成员
	Point p1,p2;//Point类的对象p1,p2 
	double len; 
};
#endif
//文件4,Line类的实现,Line.cpp
#include "Line.h"
#include "Point.h"
#include <iostream>
#include <cmath>
using namespace std;
//组合类的构造函数
Line::Line(Point xp1,Point xp2):p1(xp1),p2(xp2) {
	cout << "Calling constructor of Line" <<endl;
	double x=static_cast<double>(p1.getX()-p2.getX());
	double y=static_cast<double>(p1.getY()-p2.getY());	
	len=sqrt(x*x+y*y);
}

//组合类的复制构造函数 
Line::Line(Line &l):p1(l.p1),p2(l.p2){
	cout << "Calling the copy constructor of Line" << endl;
	len=l.len;
}
//文件5,主函数,题目2.cpp
/*
程序名:题目1.cpp
功能:请改写课本例题4-4线段(Line类),建立工程,使用多文件的组织结构实现程序(30分)。要求:
(1)文件划分:类定义文件(*.h),类实现文件(*.cpp),类使用文件(,cpp,主函数文件)。
(2)每个类的设计单独放在1个(.h)文件中,工程共包括5个文件。
(3)使用条件编译指令以免文件多次包含的情况。
(4)在Dev C++或VC中建立工程:文件-新建-项-(Basic—EmptyProject—C++项目)-新建文件夹Line
项目名称为Line,将所有文件保存在名为Line的文件夹中。
VC建立过程是:文件—>新建—>工程—>Win32 Console Application。
日期:2021.11.15
版本:1.0
*/
#include "Point.h"
#include "Line.h" 
#include <iostream>
using namespace std;

int main(){
	Point myp1(1,1),myp2(4,5);//建立Point类的对象
	Line line(myp1,myp2);//建立Line类的对象
	Line line2(line);//利用复制构造函数建立一个新对象
 	cout << "The length of the line is:";
 	cout << line.getLen() << endl;
  	cout << "The length of the line2 is:";
 	cout << line2.getLen() << endl;	
 	return 0;
} 

运行结果截图:

图片描述

图片描述

题目3:

解题思路:

Line类的数据成员包括了Point类的两个对象p1和p2,因此重数为2,而Point类的对象是Line类对象的一部分,因此需要应用聚集关系来描述。
另外,Line类的构造函数使用了Point类对象p1和p2的共有函数,可以简洁直观地将这种使用关系通过简单的依赖关系来描述
最后用带有褶角的矩形表示注释

问题:
请使用网页工具draw.io或其它或绘制UML图的工具创建一个UML图来描述上一题目中Line类与Point类的关系。

答案:

图片描述

题目4:
解题思路:
题目比较简单,注意调用未定义的类之前需要前项引用声明
程序代码:

/*
程序名:题目4.cpp
功能:定义Boat和Car两个类,二者都有weight属性,定义二者的一个友元函数getTotalWeight()计算二者重量之和。(10分)
日期:2021.11.16
版本:1.0
*/
#include <iostream>
using namespace std;
class Car;//前项引用声明 
class Boat//Boat类的定义 
{
private://私有数据成员 
	int weight;
public://外部接口
	Boat(int w){weight=w;} //构造函数
	friend void getTotalWeight(Boat &b,Car &c); //友元函数 
}; 
class Car//Car类的定义 
{
private://私有数据成员 
	int weight;
public://外部接口 
	Car(int w){weight=w;}//构造函数 
	friend void getTotalWeight(Boat &b,Car &c); //友元函数 
};
void getTotalWeight(Boat &b,Car &c)//友元函数实现 
{	
	cout<< b.weight << " & " << c.weight <<endl ;
 	int TotalWeight=b.weight+c.weight;
 	cout << "两者体重之和为:" << TotalWeight << endl;
}
int main(){
	Boat b(4);
	Car c(6);
	getTotalWeight(b,c);//调用函数计算总重 
	system("pause");
	return 0;
}

运行结果截图:
图片描述

题目5:

解题思路:
1.可以通过组合类来吧时间和日期连接起来 其中函数display使用了函数重载
2.输出当前系统时间:调用文献中
C 库函数 size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr)根据 format 中定义的格式化规则,格式化结构 timeptr 表示的时间,并把它存储在 str 中。
和C 库函数 struct tm *localtime(const time_t *timer) 使用 timer 的值来填充 tm 结构。timer 的值被分解为 tm 结构,并用本地时区表示。
注意加ctime头文件
3.输出当前时间(即对象的时间):
用cout即可实现

程序代码:

/*
程序名:题目5.cpp
功能:定义一个日期类(Date)和一个时间类(Time)。Time类是Date类的友元。
Time类中的有打印时间的成员函数void display()可以实现打印出当前的时间,例如格式为:2021年10月30日;
请编写程序设计这两个类,要求创建时间对象Today,并一次输出其中的日期和时间。(20分) 
参考文献:C++关于时间操作 https://www.runoob.com/cplusplus/cpp-date-time.html
日期:2021.11.16
版本:1.0
*/
#include <iostream>
#include <ctime>
using namespace std;

class Date//Date类的定义 
{
private://私有数据成员 
	int year;
	int month;
	int day;
public://外部接口
	Date(int y,int m,int d) 
	{
		year=y;
		month=m;
		day=d;
	}

	friend class Time;//Time类是Date类的友元类 
};
	
class Time{//Time类的定义 
private://私有数据成员 
	int hour;
	int minute;
	int second;
	Date date;
public://外部接口 
	Time(int h,int m,int s,Date D):hour(h),minute(m),second(s),date(D) {}//构造函数 
	void display();//显示系统时间 
	void display(Time t);//显示时间 
};;
void Time::display()//显示系统时间 
{
	time_t rawtime;
   struct tm *info;
   char buffer[80];
 
   time( &rawtime );
 
   info = localtime( &rawtime );
 
   strftime(buffer, 80, "%Y年%m月%d日 %H:%M:%S", info);//调用strftime函数 参考题目中文献获得 需要头文件ctime 
   cout << " 系统时间为: " << buffer << endl;
}
void Time::display(Time t){//显示时间 
	cout << "你创建的时间为:"<< t.date.year <<"年"<< t.date.month <<"月"<< t.date.day <<"日 "
							<< t.hour <<":"<< t.minute <<":"<< t.second <<endl;
}
int main(){
	Date d(2003,4,9);
	Time t(20,20,20,d);
	t.display(t);//调用函数显示时间 
	t.display();//调用函数显示系统时间 
	system("pause");
	return 0;
}

运行结果截图:

图片描述

四、实验小结

问题与解决办法:

1.问题:

函数实现显示undefined reference

解决方法:忘记了加类的作用域::

2.问题:

[Error] ISO C++ forbids in-class initialization of non-const static member ‘Grade::count’

解决方法:类的静态数据成员必须在类外进行定义和初始化,使用类名限定

3.问题:

想要给某个参数缺省值,通过构造函数初始化去进行却没有实现

解决方法:参数缺省应该在参数列表中初始化,或者再定义一个默认构造函数

心得体会:

碰到新知识不会,比方说这次实验报告中的时间操作,光看文献根本看不懂,可以通过找相关题目的代码来帮助学习

有时候看文字看不懂,但是看代码调试运行一遍就能够学会其中的知识点。

长代码报错很正常,学会单步调试慢慢去改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是一只大狸子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值