C++上機的微薄建議

C++上機實驗

對於本次的c++上機考試,我總結和預測了一下考試的內容、考點,希望到對各位有所幫助。在複習的時候能夠少走彎路,考試的時候提高做題速度,能做一道是一道。有疏漏的地方還請各位大佬見諒。
有什麼沒涉及到的經驗還請您慷慨解囊,讓我們班都考個好成績。

考試內容及考點

  1. 運算符的重載
  2. 繼承(一般爲public 公有繼承,估計到後面要考慮 virtual虛繼承)
  3. 虛函數
  4. 抽象類

類的題千萬看清楚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 會讓這種屬性的聯繫更加符合實際。

最後一定要注意空格,空格,空格。最後上傳的時候一定要盯清楚,自己的輸出和題目的輸出。
好了就說這麼多了。希望能對大家有所幫助。也希望大家能多多貢獻自己的力量,讓我們班更強大。
有諸多毛病和遺漏還請多多包涵,找我商討。我定改之。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章