C++上機實驗
對於本次的c++上機考試,我總結和預測了一下考試的內容、考點,希望到對各位有所幫助。在複習的時候能夠少走彎路,考試的時候提高做題速度,能做一道是一道。有疏漏的地方還請各位大佬見諒。
有什麼沒涉及到的經驗還請您慷慨解囊,讓我們班都考個好成績。
考試內容及考點
- 類
- 運算符的重載
- 繼承(一般爲public 公有繼承,估計到後面要考慮 virtual虛繼承)
- 虛函數
- 抽象類
類的題千萬看清楚main函數以及輸出的內容,確定出這個類所需要的數據成員和成員函數、要重載那些運算符、以及友元函數(這個是最容易被看錯的)。
好了不說廢話了,上例題
三個私有成員變量,兩個構造函數(根據創建了兩個對象,然後輸出了兩句不同的話可以知道)
兩個沒有返回值的SetClock(23,59,59)
、Show()
函數。
而這些的具體實現都在輸出結果中推測。可考試時先把具體的函數列在紙上,方便實現
在衆多類中,時間類(時、分、秒)算是複雜一點的,舉個栗子:
class Clock
{
private:
int hour,minute,second;
public :
Clock(int h=0,int m=0,int s=0)
{
hour=h;minute=m;second=s;
}
void Show()
{
cout<<hour<<":"<<minute<<":"<<second<<endl;
}
void fun(Clock &t) //fun函數起到一個對傳進來的對象的時、分、秒調整規範
{
int sum=t.hour*3600+t.second+t.minute*60;
while(sum<0) //主要對付sum小於0的情況。
{
sum+=3600*24; //回到昨天
}
t.hour=sum/3600;
t.minute=(sum-t.hour*3600)/60;
t.second=sum-t.hour*3600-t.minute*60;
t.hour%=24; //存在sum很大,雖然minute和second 可以取餘,但hour>=24
}
Clock operator++() //前置++ 下面會提到
{
this->second++;
fun(*this); //修改完就調整格式
return *this;
}
Clock operator++(int) //後置++
{
Clock old(*this);
this->second++;
fun(*this); //
return old;
}
Clock operator--() //前置++
{
this->second--;
fun(*this); //
return *this;
}
Clock operator--(int ) //後置++
{
Clock old(*this);
this->second--;
fun(*this); //
return old;
}
int operator-(Clock &t) //特別注意這裏返回值爲int ,因爲是兩個對象相減得到一個很大的數字,看詭異的輸出,就要猜到他的函數是什麼樣子
{
int sum1=hour*3600+minute*60+second;
int sum2=t.hour*3600+t.minute*60+t.second;
return sum1-sum2;
}
};
(年、月、日)
class Date
{
private:
int year,month,day;
int IsLeapYear(int y) //返回y年是否閏年,是返回1,否則返回0,可用於DaysOfMonth閏年2月的計算
{
if(y%4==0||y%400==0&&y%100!=0)
return 1;
else
return 0;
}
int DaysOfMonth(int y,int m) //返回y年m月的天數
{
int d;
switch(m)
{
case 1: case 3:case 5:case 7:case 8:
case 10: case 12:
d=31;break;
case 4: case 6: case 9: case 11:
d=30;break;
case 2:
{
d=28+IsLeapYear(y) ;
}break;
}
return d;
}
public:
Date(int y=2015,int m=5,int d=20)
{
year=y;
month=m;
day=d;
}
void Set(int y,int m,int d)
{
year=y;
month=m;
day=d;
}
void fun(Date & t) //調整日期格式的函數
{
while(true)
{
if(t.day<=DaysOfMonth(t.year,t.month)&&t.day>0&&t.month<=12&&t.month>0) //滿足格式就break
break;
if(t.day>DaysOfMonth(t.year,t.month)) //天數超出了這個月的
{
t.day-=DaysOfMonth(t.year,t.month); //調整day
t.month++; //月份++
if(t.month>12) //調整月份
{
t.month=1;
t.year++;
}
}
if(t.day<=0)
{
t.month--;
if(t.month<=0)
{
t.month=12;
t.year--;
}
t.day+=DaysOfMonth(t.year,t.month);
}
}
}
friend ostream & operator<<(ostream &os,Date &t)
{
os<<t.year<<"年"<<t.month<<"月"<<t.day<<"日";
return os;
}
Date operator++(int)
{
Date old(*this);
this->day++;
fun(*this);
return old;
}
Date operator--(int)
{
Date old(*this);
day--;
fun(*this);
return old;
}
Date &operator++()
{
day++;
fun(*this);
return *this;
}
Date &operator--()
{
day--;
fun(*this);
return *this;
}
Date operator+(int n)
{
Date t(*this);
t.day+=n;
fun(t);
return t;
}
Date operator-(int n)
{
Date t(*this);
t.day-=n;
fun(t);
return t;
}
};
上面兩個題目還有一些細節是,
1. 運算符的重載
假設有對象 T,P
前置++,即 P= ++T ,–同樣適用
Date &operator++() // 返回引用
{
day++; //先++ 再返回去賦值,原理簡單,不存在新創建對象。
return *this;
}
後置++ ,即p=T++ ;
Date operator++(int) //特別注意返回值不能是引用,而且(int)
{
Date old(*this); //需要創建一個新的對象。
this->day++; //是先賦值,後++,就是返回的這個值是未++之前的,++後的值改變的原來這個*this。
return old;
}
還有就是重載輸出>>運算符 如果看到輸出調用的不是show而是cout<<"Date 1:"<<d1<<" Date 2:"<<d2<<endl;
d2爲一個對象
那麼需要重載<<運算符函數 而且必須是友元函數
friend ostream & operator<<(ostream &os,Date &t)
{
os<<t.year<<"年"<<t.month<<"月"<<t.day<<"日"; //確立好輸出格式
return os; //返回這個對象,返回這個對象,返回這個對象
}`
如果看到`cin>>T` T爲對象,需要重載>>運算符,但一般不常見
`friend istream & operator>>(istream &is,Date &t)
{
is>>t.year>>t.month>>t.day;
return is;
}
額,需要注意的是 不要 = 的重載 還有其他的重載就不過多說明了
還有就是如果有成員函數有char a[100]
字符串類型,include <cstring>
,這個頭文件
#include<iostream>
#include<cstring>
using namespace std;
class Student
{
private:
int Id;
char name[9];
int score;
public:
Student()
{
strcpy(name,"NULL"); //根據結果這裏默認爲"NULL"
Id=0;
score=0;
}
Student(const char *n,int I,int s) //由於傳入的是"werwerar"這個常量,所以要加上const,表示它可以指向常字符串
{
strcpy(name,n);
Id=I;
score=s;
}
char* GetName()
{
return name;
}
int GetId()
{
return Id;
}
int GetScore()
{
return score;
}
void Set(const char* n,int i,int s)
{
strcpy(name,n);
Id=i;
score=s;
}
};
接下來是繼承。一般都是public 公有繼承,
#include<iostream>
using namespace std;
class Point
{
private:
int x,y;
public:
Point()
{
cout<<"Function #1 is called!"<<endl;
x=0;y=0;
}
Point(int xx,int yy)
{
x=xx;y=yy;
cout<<"Function #2 is called!"<<endl;
}
void Show()
{
cout<<"("<<x<<","<<y<<")"<<endl;
cout<<"Function #3 is called!"<<endl;
}
};
class Circle:public Point //注意基類的私有成員不能在派生類拿出來用,而且考試一般不會讓你把基類的私有變爲保護。
{
private:
int radius;
public:
Circle():Point(1000,1000) //需要注意輸出結果,對應哪種構造函數,因爲參數可能會有差異
{
cout<<"Function #4 is called!"<<endl;
radius=0;
}
Circle(int x,int y,int r):Point(x,y)
{
radius=r;
cout<<"Function #5 is called!"<<endl;
}
Circle(Point p,int r):Point(p)
{
radius=r;
cout<<"Function #6 is called!"<<endl;
}
Circle(int r):Point(100,100)
{
radius =r;
cout<<"Function #7 is called!"<<endl;
}
Circle(Point p):Point(p)
{
radius=10;
cout<<"Function #8 is called!"<<endl;
}
void Show()
{
cout<<" Radius="<<radius<<" "<<"Center=";
Point::Show(); //要調用基類的同名函數,用基類名::去訪問
cout<<"Function #9 is called!"<<endl;
}
};
多個類繼承的時候,有一種疊加的效果,四個類
#include<iostream>
#include<string>
using namespace std;
class Person
{
private:
string name;
int code;
int year,month,day;
public:
Person(string n,int c,int y,int m,int d)
{
name=n;
code=c;
year=y;
month=m;
day=d;
cout<<"Person::Constructor Function is called."<<endl;
}
virtual void Show()
{
cout<<"Person::Show Function is called."<<endl;
cout<<"NAME:"<<name<<" Code:"<<code<<" BIRTHDAY:"<<year<<"-"
<<month<<"-"<<day<<endl;
}
};
class Student: virtual public Person //虛繼承
{
private:
string name;
int code;
int year,month,day;
int score;
public:
Student(string n,int c,int y,int m,int d,int s):Person(n,c,y,m,d)
{
name=n;
code=c;
year=y;
month=m;
day=d;
score=s;
cout<<"Student::Constructor Function is called."<<endl;
}
virtual void Show()
{
cout<<"Student::Show Function is called."<<endl;
cout<<"NAME:"<<name<<" Code:"<<code<<" SCORE:"<<score<<" BIRTHDAY:"<<year<<"-"
<<month<<"-"<<day<<endl;
}
};
class Teacher:virtual public Person //虛繼承
{
private:
string name;
int code;
int year,month,day;
string department;
public:
Teacher(string n,int c,int y,int m,int d,string dd):Person(n,c,y,m,d)
{
name=n;
code=c;
year=y;
month=m;
day=d;
department=dd;
cout<<"Teacher::Constructor Function is called."<<endl;
}
virtual void Show()
{
cout<<"Teacher::Show Function is called."<<endl;
cout<<"NAME:"<<name<<" Code:"<<code<<" DEPARTMENT:"<<department<<" BIRTHDAY:"<<year<<"-"<<month<<"-"<<day<<endl;
}
};
class Graduate :public Student,public Teacher
{
private:
string name;
int code;
int year,month,day;
string department;
int score;
public:
Graduate(string n,int c,int y,int m,int d,int s,string dd)
:Person(n,c,y,m,d), //特別注意這裏的對所有基類的構造函數,因爲輸出結果“Person::Constructor Function is called. ··········
”順序是從基類往下的
Student(n,c,y,m,d,s),
Teacher(n,c,y,m,d,dd)
{
name=n;
code=c;
year=y;
month=m;
day=d;
score=s;
department=dd;
cout<<"Graduate::Constructor Function is called."<<endl;
}
void Show()
{
cout<<"Graduate::Show Function is called."<<endl;
cout<<"NAME:"<<name<<" Code:"<<code<<" SCORE:"<<score<<" DEPARTMENT:"<<department<<" BIRTHDAY:"<<year<<"-"<<month<<"-"<<day<<endl;
}
};
void Show(Person *p)
{
cout<<"Show Function is called."<<endl;
p->Show();
}
這是多重繼承。
如果是虛繼承,在你、你爸、你媽 的類裏設置了你爺的名字都是同一個人。
這裏的話,設置爺爺輩的名字,你需要分開情況,因爲你爸你媽各自帶着一個。
這只是在說明virtual對於基類的修改關係,並不意味着Graduate 上面有三種不同的對象,歸根到底,是Graduate 的三種特有的屬性,加virtual 會讓這種屬性的聯繫更加符合實際。
最後一定要注意空格,空格,空格。最後上傳的時候一定要盯清楚,自己的輸出和題目的輸出。
好了就說這麼多了。希望能對大家有所幫助。也希望大家能多多貢獻自己的力量,讓我們班更強大。
有諸多毛病和遺漏還請多多包涵,找我商討。我定改之。