面向對象程式設計(深大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() {
}