面向对象程序设计(深大oj)
一、运算符重载
A. 货币加减(输入输出重载) 题目描述
定义CMoney类,包含元、角、分三个数据成员,友元函数重载‘+’、‘-’,实现货币的加减运算(假设a-b中a的金额始终大于等于b的金额),重载输入、输出,实现货币的输入,输出。
读入最初的货币值,对其不断进行加、减操作,输出结果。
可根据需要,为CMoney类添加构造函数或其它成员函数。
输入
测试次数
每组测试数据格式如下:
第一行,初始货币:元 角 分
第二行开始,每行一个操作:add 元 角 分(加)、minus 元 角 分(减)、stop(结束)
输出
对每组测试数据,输出操作终止后的货币金额,具体输出格式见样例。
class CMoney
{
public:
int yuan, jiao, fen;
CMoney() {
}
CMoney(int yuan, int jiao, int fen) {
this->yuan = yuan;
this->jiao = jiao;
this->fen = fen;
}
friend CMoney operator+(CMoney &a, CMoney& b);
friend CMoney operator-(CMoney &a, CMoney& b);
};
主要就是类中的操作符重载(可以友元重载,也可以直接重载,根据你需要的参数来决定)
贴一个加法的实现:
CMoney operator+(CMoney &a, CMoney& b) {
CMoney c(0, 0, 0);
int a1 = (a.yuan) * 100 + (a.jiao) * 10 + (a.fen);
int b1 = (b.yuan) * 100 + (b.jiao) * 10 + (b.fen);
int c1 = a1 + b1;
c.yuan = c1 / 100;
c1 %= 100;
c.jiao = c1 / 10;
c1 %= 10;
c.fen = c1;
return c;
}
以及输出的实现: (因为输出是可以接连输出的,所以返回的也是输出流)
ostream &operator<<(ostream &stream, CMoney & c) {
stream << c.yuan << "元" << c.jiao << "角" << c.fen << "分" << endl;
return stream;
}
B. 矩形关系(运算符重载) 题目描述
假设坐标采用二维平面坐标。
定义点类CPoint,包含属性x,y(整型)。方法有:带参构造函数,getX,getY分别返回点的x坐标,y坐标。
定义矩形类CRectangle,包含属性:矩形的左上角坐标leftPoint,右下角坐标rightPoint。类中方法有:
1)带参构造函数,初始化矩形的左上角、右下角
2)重载>运算符,参数为CPoint点对象,假设为p,若p在矩形内,返回true,否则返回false。
3)重载>运算符,第一个矩形若包含第二个矩形(部分边界可以相等),返回true,否则返回false。(要求该函数调用2)实现)
4)重载==运算符,判断两个矩形是否一致,返回true或false。
5)重载*运算符,判断两个矩形是否有重叠部分,返回true或false。
6)重载类型转换运算符,计算矩形的面积并返回,面积是整型。
7)重载《运算符,输出矩形的两个角坐标和面积,具体格式见样例。
输入2个矩形,计算面积,判断矩形的关系。主函数如下,不可修改。
class CPoint {
public:
int x, y;
CPoint(int x, int y){
this->x = x;
this->y = y;
};
int getX() {
return this->x;
}
int getY() {
return this->y;
}
bool operator == (const CPoint &cpoint) {
return (x == cpoint.x) && (y == cpoint.y);
}
};
这次再贴一个在类内直接重载的例子
C. 集合(运算符重载) 题目描述
集合是由一个或多个确定的元素所构成的整体。集合的运算有并、交、相对补等。
集合A和集合B的交集:由属于A且属于B的相同元素组成的集合。
集合A和集合B的并集:由所有属于集合A或属于集合B的元素所组成的集合。
集合B关于集合A的相对补集,记做A-B:由属于A而不属于B的元素组成的集合。
假设集合A={10,20,30},集合B={1,10,50,8}。则A与B的并是{10,20,30,1,50,8},A与B的交是{10},B关于A的相对补集是{20,30}。
定义整数集合类CSet,属性包括:集合中的元素个数n,整型指针data存储集合中的元素。
方法有:重载输出,按样例格式输出集合中的元素。
重载+运算符,求集合A和集合B的并集,并返回结果集合。
重载-运算符,求集合B关于集合A的相对补集,并返回结果集合。
重载*运算符,求集合A和集合B的交集,并返回结果集合。
主函数输入集合A、B的数据,计算集合的并、交、相对补。
可根据题目,为CSet类添加需要的成员函数。
一个比较坑的地方就是这里的参数需要加上const,因为不对其值进行修改,否则oj贵不了
Set operator - (const Set &set1, const Set &set2)
{
Set res;
vector<int> re;
for (auto da : set1.data) {
int f = 0;
for (auto r : set2.data) {
if (r == da) {
f = 1;
}
}
if (f == 0) {
re.push_back(da);
}
}
res.data = re;
return res;
}
二、虚函数和多态
计算学生成绩等级(虚函数和多态) 题目描述
请设计3个类,分别是学生类Student,本科生类Undergraduate,研究生类Postgraduate,其中Student类是基类,它包含基本的学生信息,如姓名、类别(本科生还是研究生)、所学课程(这里假定为3门课,用数组表示)成绩和成绩等级等;Undergraduate类和Postgraduate都是Student类的派生类,它们之间的主要差别是计算3门课程平均成绩等级的方法有所不同,研究生的标准要比本科生的标准高一些,如下表所示:
本科生标准 研究生标准 80~100优秀 90~100优秀 70~80良好 80~90良好 60~70一般 70~80一般 50~60及格 60~70及格 50以下不及格 60以下不及格 学生Student基类框架如下所示:
class Student{
protected:
string name; //学生姓名
int type; //学生类别:1表示本科生,2表示研究生
int courses[3]; //3门课的成绩
string courseGrade; //成绩等级
public:
Student(string n,string t,int a1,int a2,int a3);//构造方法
virtual void calculateGrade()=0;//计算成绩等级
void print();//输出信息
};
以Student为基类,构建出Undergraduate、Postgraduate两个类。
生成上述类并编写主函数,要求主函数中有一个基类指针,生成基类动态数组,来接收子类对象。
输入
第一行表示测试次数。从第二行开始,每个测试用例占一行,每行数据意义如下:学生姓名、学生类别(1为本科生,2为研究生)、3门课的成绩。
输出
学生姓名、类别、成绩等级
主要就是哪些方法(比如下面的计算成绩的方法需要被子类改来改去的就用虚函数修饰),然后赋值为0,接着在子类里面(不加修饰符)地修改即可
class Student
{
protected:
string name;
int type;
int courses[3];
string courseGrade;
public:
Student(string n, int t, int a1, int a2, int a3)
{
this->name = n;
this->type = t;
this->courses[0] = a1;
this->courses[1] = a2;
this->courses[2] = a3;
}
virtual void calculateGrade() = 0;
virtual ~Student() = 0;
void print()
{
cout << this->name << "," << ty(this->type) << "," << this->courseGrade << endl;
}
};
Student::~Student() {
}
后续不定期补全
|