C++实验4 对象作为数据成员

实验四 对象作为数据成员

1 实验目的

学习对象作为类的数据成员的使用方法,学习对象数据成员的初始化以及“成员初始化器”的使用方法。

2 实验内容

2.1 使用 Date 类,定义 Employee 类

(1)问题描述

在《实验三 面向对象初步》中,设计了日期类 Date。本次实验将设计雇员类 Employee,并将日期类 Date 作为雇员类 Employee 的内嵌数据成员。日期类
Date 和雇员类 Employee 的声明分别如下所示:

class Date {
public:
/* 默认构造函数,以fullyear的形式给出年月日,默认值为1990年1月1日,同时设置日
期分隔符为“-” */
Date(int year = 1990, int month = 1, int day = 1);
/* get、set方法 */
// 设置日期,如果有非法的月或日,将其置为1
void setDate(int year, int month, int day);
void setYear(int year);
int getYear();
void setMonth(int month);
int getMonth();
void setDay(int month);
int getDay();
void setSeparator(char separator);
/* 输出函数,请使用setfill(‘0’)和setw(2)。*/
void printFullYear(); //以YYYY-MM-DD的形式打印,2011-01-08
void printStandardYear(); //以YY-MM-DD的形式打印,比如11-01-08
/* 计算当前日期与参数日期之间相差几个整年,仅考虑参数日期比当前日期晚的情况。
注意参数为日期对象的引用。*/
int fullYearsTo(Date &date);
/* 计算当前日期与参数日期之间相差多少天(考虑闰年),如果参数日期在当前日期之前,
返回负数。注意参数为日期对象的引用。*/
int daysTo(Date &date);
/* 新增函数,可以被daysTo函数调用 */
int getDayOfYear(); //计算当前日期是本年的第几天
int getLeftDaysYear(); //计算当前日期距本年结束还有几天,不包括当前日期这一private:
int year;
int month;
int day;
char separator; // 日期分隔符
/* 新增数据成员和函数成员 */
/*声明静态常变量,每月的天数,在.cpp文件中定义并初始化 */
static int DAYS_PER_MONTH[12];
/*根据年和月,判断参数日期是否合法。如果合法,返回day,否则返回1。*/
int checkDay(int day);
bool isLeapyear(int year);//断参数年是否是闰年。
};
class Employee{
public:
//构造函数,使用“成员初始化器”初始化数据成员
Employee(string, string, Date &, Date &);
//打印员工的信息。调用Date类的print函数,打印员工的生日和雇佣日期。
void print();
//计算员工在参数指定的日期时,满多少岁。请使用Date类的fullYearsTo函数
int getAge(Date &date);
//计算该员工在参数指定的日期时,工作满了多少年。
int getYearsWorked(Date &date);
//计算该员工在参数指定的日期时,工作了多少天。使用Date类的daysTo函数。
int getDaysWorked(Date &date);
~Employee(); //析构函数
private:
string firstName;
string lastName;
Date birthDate; //内嵌对象,出生日期
Date hireDate; //内嵌对象,雇用日期
};

(2)问题要求

可以满足以下主函数的要求:

#include <iostream>
#include <string>
using namespace std;
void main() {
Date birth(1969, 8, 11);
Date hire(1998, 4, 1);
Date today(2010, 4, 30);
Employee manager("Bob", "Blue", birth, hire);
cout << endl;
manager.print();
cout << endl;
cout << manager.getAge(today) << endl;
cout << manager.getDaysWorked(today) << endl;
}

输出结果如下,其中的注释仅为了说明运行结果,实际执行时不必输出。

//调用manager.print()后,打印以下信息
Blue, Bob Hired: 1998-04-01 Birthday: 1969-08-11
//调用manager.getAge(today)后,打印以下信息
40 // 工作满了40年
//调用manager.getDaysWorked(today)
4412 // 已工作了4412天 3
4

源代码

Date.cpp
#include <iostream>
#include <iomanip>
#include "Date.h"

using namespace std;

// constructor confirms proper value for month; calls utility function checkDay to confirm proper value for day
Date::Date(int year, int month, int day) {
	setYear(year);
	setMonth(month);
	setDay(day);
	setSeparator('-');
}

void Date::setYear(int year) {
	this->year = year;
}

void Date::setMonth(int month) {
	if (month >= 0 && month <= 12)
		this->month = month;
	else {
		this->month = 1;
		cout << "Invalid month (" << month << ") set to 1.\n";
	}
}

void Date::setDay(int day) {
	this->day = checkDay(day); // validate the day.
}

void Date::setSeparator(char c) {
	separator = c;
}

int Date::getYear() const {
	return year;
}

int Date::getMonth() const {
	return month;
}

int Date::getDay() const {
	return day;
}

char Date::getSeparator() const {
	return separator;
}

//Print Date object in form YYYY-MM-DD
void Date::printFullYear() const {
	cout << year << separator
		<< setfill('0') << setw(2) << month << separator
		<< setw(2) << day;
}

//Print Date object in form YY-MM-DD
void Date::printStandardYear() const {
	cout << setfill('0') << setw(2) << (year % 100) << separator
		<< setw(2) << month << separator
		<< setw(2) << day;
}

// 计算当前日期与参数日期之间相差几个整年,注意参数为日期对象的引用
int Date::fullYearsTo(const Date &date) const {
	// 如果当前日期的月小于参数日期的月;
	// 或者月相等,并且当前日期的日小于等于参数日期的日
	if ((month < date.month) || (month == date.month && day <= date.day))
		return date.year - year;
	else
		return date.year - year - 1;
}

// 计算当前日期比参数日期晚了多少天(考虑闰年)
// 如果参数日期晚于当前日期,返回负数,注意参数为日期对象的引用。
int Date::operator -(const Date &date) const {
	const Date* startDate;		// 开始日期;
	const Date* endDate;		// 结束日期;
	bool ascent = true;         // 当前日期晚于参数日期,则为真。默认为真。

	// 如果在同一年中
	if (this->year == date.year) {
		return this->getDayOfYear() - date.getDayOfYear();
	}

	// 不在同一年中,且当前日期晚	
	if (this->year > date.year) 	{
		startDate = &date;
		endDate = this;
		// 如果当前日期早
	} else {
		startDate = this;
		endDate = &date;
		ascent = false;
	}

	// 先加上开始日期到该年结束的天数
	int offsetDays = startDate->getLeftDaysYear();

	// 再加上开始日期和结束日期之间的所有年的天数 (不包括起止年)
	for (int i = startDate->year + 1; i < endDate->year; i++) {
		offsetDays += getYearDays(i);
	}

	// 再加上结束日期时,该年已经过的天数
	offsetDays += endDate->getDayOfYear();

	
	if (ascent)   // 如果是升序
		return offsetDays;
	else		  // 如果是降序,返回负数
		return 0 - offsetDays;
}

// 计算当前日期是本年的第几天
int Date::getDayOfYear() const {
	int days = 0;

	for (int i = 1; i<month; i++) {
		days += daysPerMonth[i - 1];
	}
	days += day;
	if (isLeapyear(year) && month > 2)
		days++;

	return days;
}

// 计算当前日期距本年结束还有几天
// 不包括当前日期这一天
int Date::getLeftDaysYear() const {
	return getYearDays(year) - getDayOfYear();
}

// 计算某一年有多少天
int Date::getYearDays(int year) const {
	if (isLeapyear(year))
		return 366;
	return 365;
}

// utility function to confirm proper day value based on month and year; handle leap years, too.
int Date::checkDay(int testDay) const {
	if (testDay > 0 && testDay <= daysPerMonth[month - 1])
		return testDay;

	if (isLeapyear(year) && month == 2 && testDay == 29)
		return testDay;

	cout << "Invalid day (" << testDay << ") set to 1.\n";
	return 1;
}

bool Date::isLeapyear(int year) const {
	return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}

void main() {
	Date birthDate(1991, 1, 11);    // 我的生日
	birthDate.printFullYear();      // 打印:1969-08-11
	cout << endl;

	birthDate.printStandardYear(); // 打印:69-08-11
	cout << endl;

	birthDate.setSeparator('/');
	birthDate.printFullYear(); // 打印:1969/08/11
	cout << endl;
	cout << endl;

	Date date(2000, 2, 29);
	cout << date.getDayOfYear() << endl;
	cout << birthDate.fullYearsTo(date) << endl; // 打印:40,满四十岁
	cout << date - birthDate << endl; // 打印14857,活了14857天了

	Date date2(1949, 10, 1);
	cout << birthDate - date2 << endl; // 打印-7254,共和国比我早诞生了7254天
}

const int Date::daysPerMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

istream & operator >>(istream &input, Date &date) {
	input >> date.year >> date.month >> date.day;
	return input;
}

ostream & operator <<(ostream &output, const Date &date) {
	output << date.year << "-" << date.month << "-" << date.day;
	return output;
}
Date.h
#ifndef DATE_H
#define DATE_H
#include <iostream>
using namespace std;

class Date {
	friend istream & operator>>(istream &, Date &);
	friend ostream & operator<<(ostream &, const Date &);
public:
	// 默认构造函数,以fullyear的形式给出年月日,
	// 默认值为1900年1月1日
	// 同时设置日期分隔符为“-”
	Date(int = 1900, int = 1, int = 1);

/// 设置、获取函数///
	// 设置日期,如果有非法的月或日,将其置为
	void setDate(int, int , int);
	void setYear(int);
	int getYear() const;
	void setMonth(int);
	int getMonth() const;
	void setDay(int);
	int getDay() const;
	void setSeparator(char);
	char getSeparator() const;

/// 输出函数,使用setfill和setw ///
	void printFullYear() const;	// 以YYYY-MM-DD的形式打印,比如2010-01-08
	void printStandardYear() const;	// 以YY-MM-DD的形式打印,比如2010-01-08

///  计算函数  ///
	// 计算当前日期与参数日期之间相差几个整年,注意参数为日期对象的引用
	int fullYearsTo(const Date& date) const; 

	// 计算当前日期比参数日期晚了多少天(考虑闰年)。如果参数日期晚于当前日期,返回负数,注意参数为日期对象的引用。
	int operator-(const Date& date) const;	
	// 计算当前日期是本年的第几天
	int getDayOfYear() const;
	
	// 计算当前日期距本年结束还有几天。不包括当前日期这一天
	int getLeftDaysYear() const;

private:
	int year;
	int month;
	int day;
	char separator;						// 日期分隔符
	static const int daysPerMonth[12];	// 声明静态常变量,每月的天数。在.cpp文件中定义并初始化
	int checkDay( int ) const;			// 根据年和月,判断参数日期是否合法。
	bool isLeapyear( int ) const;		// 判断参数年是否是闰年。
	int getYearDays( int ) const;		// 计算参数年有多少天
};

#endif
Employee.cpp
#include <iostream>
#include <iomanip>
#include "Employee.h"
#include "Date.h"

using namespace std;

Employee::Employee(const string first, const string last,
		const Date &dateOfBirth, const Date &dateOfHire)
		: firstName(first), lastName(last),
		  birthDate(dateOfBirth),
		  hireDate(dateOfHire) { }

void Employee::print() const {
	cout << lastName << ", " << firstName << " Hired: ";
	cout << hireDate;
	cout << ", Birthday: ";
	cout << birthDate << endl;
}
int Employee::getAge(const Date& date) const {
	return birthDate.fullYearsTo(date);
}

int Employee::getYearsWorked(const Date& date) const {
	return hireDate.fullYearsTo(date);
}

int Employee::getDaysWorked(const Date& date) const {
	return date - hireDate;
}

void main() {
	Date birth(1969, 8, 11);
	Date hire(1998, 4, 1);

	Date today(2010, 4, 30);

	Employee manager("Bob", "Blue", birth, hire);
	cout << endl;

	manager.print();

	cout << "到";
	today.printFullYear();
	cout << "为止" << endl;
	cout << "   雇员已满" << manager.getAge(today) << "岁" << endl;
	cout << "   雇员已工作了" << manager.getDaysWorked(today) << "天" << endl;

}
Employee.h
#include <string>
#include "Date.h"

using namespace std;

class Employee {
public:
	Employee(const string, const string, const Date &, const Date &);
	void print() const;

	// 计算员工在参数指定的日期时,满多少岁
	int getAge(const Date &date) const;

	// 计算该员工工作满了多少年
	int getYearsWorked(const Date &date) const;
	// 计算该员工工作了多少天
	int getDaysWorked(const Date &date) const;

private:
	string firstName;
	string lastName;
	const Date birthDate; // composition: member object
	const Date hireDate;
};

2.2 设计一个 CD 播放机 CDPlayer

(1)问题描述

设计一个CD播放机CDPlayer,它能够播放CD中的歌。其中,CD类、CDPlayer
类的声明分别如下所示:

class CD {
public:
CD(string name, string songs[]);
string getSinger(); // 获得歌手的名称
string getSong(int index); // 获得某首歌的歌名
void listSongs(); // 列出CD的内容
private:
string singer; // 歌手的名字。
string songs[6]; // 每张专辑6首歌的名字。
};
class CDPlayer {
public:
CDPlayer();
/*提供给用户一个菜单,通过这个菜单,用户可以选择:
1. 插入CD
2. 播放CD
3. 弹出CD
0. 关机 */
void showMenu();
/*插入CD. void insertCD(CD* cd),形参是指向CD对象的指针。如果CDPlayer中已经
有CD,提示先取出CD;如果CDPlayer中没有CD,显示插入了哪位歌星的CD。*/
void insertCD(CD *cd);
/*弹出CD. CD *ejectCD(),返回值是指向该CD对象的指针。如果CDPlayer中已经有CD,
显示弹出了哪位歌星的CD,返回该CD的指针;如果CDPlayer中没有CD,提示CDPlayer中
没有CD,返回NULL。*/
CD *ejectCD();
/*播放CD。如果CDPlayer中已经有CD,显示正在播放哪位歌星的CD,并打印CD中歌曲的
清单;如果CDPlayer中没有CD,显示CDPlayer中没有CD,并提示用户插入CD。*/
void play();
private:
/* 插入CDPlayer中的CD,它是指向CD对象的指针。没有CD时,为null。使用指针,很
好地模拟 了CD对象不是播放器的一部分,播放器只是读取放入其中的CD的内容。*/
CD *cd;
bool cdIn; // CDPlayer中是否已经插入CD
};

主函数如下:

void main() {
string name;
string songs[6];
cout << "制造CD......" << endl;
// 输入歌手名字
cout << " Singer's Name: " << endl;
cin >> name; // 输入:周杰伦
// 输入该歌手的六首歌名(青花瓷、菊花台、双节棍等)
for (int i = 0; i < 6; i++) {
cout << " song" << (i+1) << "#: ";
cin >> songs[i];
}
CD cd(name, songs); //制造CD
cd.listSongs(); //显示CD的内容
CDPlayer player; //制造CDplayer
player.showMenu(); //生成播放机的按钮
/* 播放 */
player.play(); //打印:Please insert CD first
/* 插入CD */
player.insertCD(&cd); //打印:插入了周杰伦的CD......
/* 播放 */
player.play(); //打印:正在播放周杰伦的CD......

player.ejectCD(); //打印:弹出了周杰伦的CD......
/* 另造一张CD,歌手和歌的录入省略。*/
CD cd2(name2, songs2);
player.insertCD(&cd2);
player.play();
} 

(2)问题要求
在这里插入图片描述
在这里插入图片描述

源代码

CD.cpp
#include <iostream>
#include <string>
#include "CD.h"

using namespace std;

CD::CD(string name, string songs[]) {
	singer = name;
	for (int i = 0; i < 6; i++)
		CD::songs[i] = songs[i];
}

string CD::getSinger() {
	return singer;
}

string CD::getSong(int index) {
	return songs[index];
}

void CD::listSongs() {
	cout << "Singer: " << singer << endl;
	for (int i = 0; i < 6; i++)
		cout << "  " << (i + 1) << ". " << (*songs)[i] << endl;
}

CD.h
#include <string>
using namespace std;

class CD {
public:

	CD(string name, string songs[]);

	string getSinger();
	string getSong(int index);
	void listSongs();

private:
	string singer;   // 歌手的名字。
	string songs[6]; // 每张专辑6首歌的名字。
};

CDPlayer.cpp
#include <iostream>
#include <string>
#include "CDPlayer.h"

using namespace std;

CDPlayer::CDPlayer() {
	cd = NULL;
	cdIn = false;
}

void CDPlayer::insertCD(CD *cd) {
	if (cdIn)
		cout << "CD already in, to change, eject it first......\n";
	else {
		CDPlayer::cd = cd;
		cdIn = true;
		cout << "插入了" << cd->getSinger() << "的CD......\n";
	}
}

CD* CDPlayer::ejectCD() {
	CD* temp = cd;
	if (cdIn) {
		cout << "弹出了" << cd->getSinger() << "的CD......\n";
		cdIn = false;
		cd = 0;
		return temp;
	} else {
		cout << "No CD.\n";
		return NULL;
	}
}

void CDPlayer::play() {
	if (cdIn) {
		cout << "正在播放" << cd->getSinger() << "的CD......\n";
		cd->listSongs();
		/*for (int i = 0; i < 6; i++)
		 cout << "  Song" << (i+1) << "#: " << cd->getSong(i) << endl;*/
	} else
		cout << "Please insert CD first\n";
}

void CDPlayer::showMenu() {
	cout << endl;
	cout << "**************************************\n";
	cout << "*  1. 播放CD                         *\n";
	cout << "*  2. 插入CD                         *\n";
	cout << "*  3. 弹出CD                         *\n";
	cout << "*  0. 关机                           *\n";
	cout << "**************************************\n";
}

int main() {
	string name;
	string songs[6];

	cout << "\n制造CD......\n";
	// 输入歌手名字 
	cout << "  Singer's Name: ";
	cin >> name; // 输入:周杰伦

	// 输入该歌手的六首歌名(青花瓷、菊花台、三节棍等)
	for (int i = 0; i < 6; i++) {
		cout << "  song" << (i + 1) << "#: ";
		cin >> songs[i];
	}

	// 制造CD
	CD cd(name, songs);
	// 显示CD的内容
	cd.listSongs();

	// 制造CDplayer
	CDPlayer player;

	// 生成播放机的按钮
	player.showButtons();

	// 播放
	player.play(); // 打印:Please insert CD first
	// 插入CD
	player.insertCD(&cd); // 打印:插入了周杰伦的CD......
	// 播放
	player.play(); // 打印:正在播放周杰伦的CD......
				   //         song1#: 青花瓷
				   //         song2#: 菊花台
				   //         song3#: 三节棍
				   //         song4#: 东风破
				   //         song5#: 珊瑚海
				   //         song6#: 稻香
	player.ejectCD(); // 打印:弹出了周杰伦的CD......

	return 0;
}

CDPlayer.h
#include "CD.h"

class CDPlayer {
public:
	CDPlayer();

	// 提供给用户一个菜单.
	// 通过这个菜单,用户可以选择
	// 1. 插入CD
	// 2. 播放CD
	// 3. 弹出CD
	// 0. 关机
	void showMenu();

	// 插入CD,形参是指向CD对象的指针.
	// 如果CDPlayer中已经有CD,提示先取出CD;
	// 如果CDPlayer中没有CD,显示插入了哪位歌星的CD.
	void insertCD(CD* cd);

	// 弹出CD,返回值是指向该CD对象的指针.
	// 如果CDPlayer中已经有CD,显示弹出了哪位歌星的CD,返回该CD的指针;
	// 如果CDPlayer中没有CD,提示CDPlayer中没有CD,返回NULL.
	CD* ejectCD();

	// 播放CD.
	// 如果CDPlayer中已经有CD,显示正在播放哪位歌星的CD;
	// 如果CDPlayer中没有CD,显示CDPlayer中没有CD,
	// 并提示用户插入CD.
	void play();

private:
	CD* cd; // 插入CDPlayer中的CD,它是指向CD对象的指针
	bool cdIn; // CDPlayer中是否已经插入CD
};

发布了172 篇原创文章 · 获赞 81 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/weixin_43074474/article/details/104682491
今日推荐