2016年計算機(jī)二級C++復(fù)習(xí)資料:類的轉(zhuǎn)換

字號:


    C++的內(nèi)部數(shù)據(jù)類型遵循隱式類型轉(zhuǎn)換規(guī)則。假設(shè)某個表達(dá)市中使用了一個短整型變量,而編譯器根據(jù)上下文認(rèn)為這兒需要是的長整型,則編譯器就會根據(jù)類型轉(zhuǎn)換規(guī)則自動把它轉(zhuǎn)換成長整型,這種隱式轉(zhuǎn)換出現(xiàn)在賦值、參數(shù)傳遞、返回值、初始化和表達(dá)式中。我們也可以為類提供相應(yīng)的轉(zhuǎn)換規(guī)則。
    對一個類建立隱式轉(zhuǎn)換規(guī)則需要構(gòu)造一個轉(zhuǎn)換函數(shù),該函數(shù)作為類的成員,可以把該類的對象和其他數(shù)據(jù)類型的對象進(jìn)行相互轉(zhuǎn)換。聲明了轉(zhuǎn)換函數(shù),就告訴了編譯器,當(dāng)根據(jù)句法判定需要類型轉(zhuǎn)換時,就調(diào)用函數(shù)。
    有兩種轉(zhuǎn)換函數(shù)。一種是轉(zhuǎn)換構(gòu)造函數(shù);另一種是成員轉(zhuǎn)換函數(shù)。需要采用哪種轉(zhuǎn)換函數(shù)取決于轉(zhuǎn)換的方向。
    一、轉(zhuǎn)換構(gòu)造函數(shù)
    當(dāng)一個構(gòu)造函數(shù)僅有一個參數(shù),且該參數(shù)是不同于該類的一個數(shù)據(jù)類型,這樣的構(gòu)造函數(shù)就叫轉(zhuǎn)換構(gòu)造函數(shù)。轉(zhuǎn)換構(gòu)造函數(shù)把別的數(shù)據(jù)類型的對象轉(zhuǎn)換為該類的一個對象。和其他構(gòu)造函數(shù)一樣,如果聲明類的對象的初始化表同轉(zhuǎn)換構(gòu)造函數(shù)的參數(shù)表相匹配,該函數(shù)就會被調(diào)用。當(dāng)在需要使用該類的地方使用了別的數(shù)據(jù)類型,便宜器就會調(diào)用轉(zhuǎn)換構(gòu)造函數(shù)進(jìn)行轉(zhuǎn)換。
    #include iostream.h
    #include time.h
    #include stdio.h
    class Date
    {
    int mo, da, yr;
    public:
    Date(time_t);
    void display();
    };
    void Date::display()
    {
    char year[5];
    if(yr<10)
    sprintf(year,0%d,yr);
    else
    sprintf(year,%d,yr);
    cout< }
    Date::Date(time_t now)
    {
    tm* tim=localtime(&now);
    da=tim->tm_mday;
    mo=tim->tm_mon+1;
    yr=tim->tm_year;
    if(yr>=100) yr-=100;
    }
    int main()
    {
    time_t now=time(0);
    Date dt(now);
    dt.display();
    return 0;
    }
    本程序先調(diào)用time()函數(shù)來獲取當(dāng)前時間,并把它賦給time_t對象;然后程序通過調(diào)用Date類的轉(zhuǎn)換構(gòu)造函數(shù)來創(chuàng)建一個Date對象,該對象由time_t對象轉(zhuǎn)換而來。time_t對象先傳遞給localtime()函數(shù),然后返回一個指向tm結(jié)構(gòu)(time.h文件中聲明)的指針,然后構(gòu)造函數(shù)把結(jié)構(gòu)中的日月年的數(shù)值拷貝給Date對象的數(shù)據(jù)成員,這就完成了從time_t對象到Date對象的轉(zhuǎn)換。
    二、成員轉(zhuǎn)換函數(shù)
    成員轉(zhuǎn)換函數(shù)把該類的對象轉(zhuǎn)換為其他數(shù)據(jù)類型的對象。在成員轉(zhuǎn)換函數(shù)的聲明中要用到關(guān)鍵字operator。這樣聲明一個成員轉(zhuǎn)換函數(shù):
    operator aaa();
    在這個例子中,aaa就是要轉(zhuǎn)換成的數(shù)據(jù)類型的說明符。這里的類型說明符可以是任何合法的C++類型,包括其他的類。如下來定義成員轉(zhuǎn)換函數(shù);
    Classname::operator aaa()
    類名標(biāo)識符是聲明了該函數(shù)的類的類型說明符。上面定義的Date類并不能把該類的對象轉(zhuǎn)換回time_t型變量,但可以把它轉(zhuǎn)換成一個長整型值,計算從2000年1月1日到現(xiàn)在的天數(shù)。
    #include iostream.h
    class Date
    {
    int mo,da,yr;
    public:
    Date(int m,int d,int y) {mo=m; da=d; yr=y;}
    operator int(); //聲明
    };
    Date::operator int() //定義
    {
    static int dys[]={31,28,31,30,31,30,31,31,30,31,30,31};
    int days=yr-2000;
    days*=365;
    days+=(yr-2000)/4;
    for(int i=0;i days+=dys[i];
    days+=da;
    return days;
    }
    int main()
    {
    Date now(12,24,2003);
    int since=now;
    cout< return 0;
    }
    三、類的轉(zhuǎn)換
    上面兩個例子都是C++類對象和內(nèi)部數(shù)據(jù)對象之間的相互轉(zhuǎn)換。也可以定義轉(zhuǎn)換函數(shù)來實(shí)現(xiàn)兩個類對象之間的相互轉(zhuǎn)換。
    #include iostream.h
    class CustomDate
    {
    public:
    int da, yr;
    CustomDate(int d=0,int y=0) {da=d; yr=y;}
    void display()
    {
    cout< }
    };
    class Date
    {
    int mo, da, yr;
    public:
    Date(int m=0,int d=0,int y=0) {mo=m; da=d; yr=y;}
    Date(const CustomDate&); //轉(zhuǎn)換構(gòu)造函數(shù)
    operator CustomDate(); //成員轉(zhuǎn)換函數(shù)
    void display()
    {
    cout< }
    };
    static int dys[] = {31,28,31,30,31,30,31,31,30,31,30,31};
    Date::Date(const CustomDate& jd)
    {
    yr=jd.yr;
    da=jd.da;
    for(mo=0;mo<11;mo++)
    if(da>dys[mo]) da-=dys[mo];
    else break;
    mo++;
    }
    Date::operator CustomDate()
    {
    CustomDate cd(0,yr);
    for(int i=0;i cd.da+=da;
    return cd;
    }
    int main()
    {
    Date dt(12,24,3);
    CustomDate cd;
    cd = dt; //調(diào)用成員轉(zhuǎn)換函數(shù)
    cd.display();
    dt = cd; //調(diào)用轉(zhuǎn)換構(gòu)造函數(shù)
    dt.display();
    return 0;
    }
    這個例子中有兩個類CustomDate和Date,CustomDate型日期包含年份和天數(shù)。
    這個例子沒有考慮閏年情況。但是在實(shí)際構(gòu)造一個類時,應(yīng)該考慮到所有問題的可能性。
    在Date里中具有兩種轉(zhuǎn)換函數(shù),這樣,當(dāng)需要從Date型變?yōu)镃ustomDate型十,可以調(diào)用成員轉(zhuǎn)換函數(shù);反之可以調(diào)用轉(zhuǎn)換構(gòu)造函數(shù)。
    不能既在Date類中定義成員轉(zhuǎn)換函數(shù),又在CustomDate類里定義轉(zhuǎn)換構(gòu)造函數(shù)。那樣編譯器在進(jìn)行轉(zhuǎn)換時就不知道該調(diào)用哪一個函數(shù),從而出錯.
    四、轉(zhuǎn)換函數(shù)的調(diào)用
    C++里調(diào)用轉(zhuǎn)換函數(shù)有三種形式:第一種是隱式轉(zhuǎn)換,例如編譯器需要一個Date對象,而程序提供的是CustomDate對象,編譯器會自動調(diào)用合適的轉(zhuǎn)換函數(shù)。另外兩種都是需要在程序代碼中明確給出的顯式轉(zhuǎn)換。C++強(qiáng)制類型轉(zhuǎn)換是一種,還有一種是顯式調(diào)用轉(zhuǎn)換構(gòu)造函數(shù)和成員轉(zhuǎn)換函數(shù)。下面的程序給出了三中轉(zhuǎn)換形式:
    #include iostream.h
    class CustomDate
    {
    public:
    int da, yr;
    CustomDate(int d=0,int y=0) {da=d; yr=y;}
    void display()
    {
    cout< }
    };
    class Date
    {
    int mo, da, yr;
    public:
    Date(int m,int d,int y)
    {
    mo=m; da=d; yr=y;
    }
    operator CustomDate();
    };
    Date::operator CustomDate()
    {
    static int dys[]={31,28,31,30,31,30,31,31,30,31,30,31};
    CustomDate cd(0,yr);
    for(int i=0;i cd.da+=da;
    return cd;
    }
    int main()
    {
    Date dt(11,17,89);
    CustomDate cd;
    cd = dt;
    cd.display();
    cd = (CustomDate) dt;
    cd.display();
    cd = CustomDate(dt);
    cd.display();
    return 0;
    }
    五、轉(zhuǎn)換發(fā)生的情形
    上面的幾個例子都是通過不能類型對象之間的相互賦值來調(diào)用轉(zhuǎn)換函數(shù),還有幾種調(diào)用的可能:
    參數(shù)傳遞
    初始化
    返回值
    表達(dá)式語句
    這些情況下,都有可能調(diào)用轉(zhuǎn)換函數(shù)。
    下面的程序不難理解,就不分析了。
    #include iostream.h
    class CustomDate
    {
    public:
    int da, yr;
    CustomDate() {}
    CustomDate(int d,int y) { da=d; yr=y;}
    void display()
    {
    cout< }
    };
    class Date
    {
    int mo, da, yr;
    public:
    Date(int m,int d,int y) { mo=m; da=d; yr=y; }
    operator CustomDate();
    };
    Date::operator CustomDate()
    {
    static int dys[]={31,28,31,30,31,30,31,31,30,31,30,31};
    CustomDate cd(0,yr);
    for (int i=0;i cd.da+=da;
    return cd;
    }
    class Tester
    {
    CustomDate cd;
    public:
    explicit Tester(CustomDate c) { cd=c; }
    void display() { cd.display(); }
    };
    void dispdate(CustomDate cd)
    {
    cd.display();
    }
    CustomDate rtndate()
    {
    Date dt(9,11,1);
    return dt;
    }
    int main()
    {
    Date dt(12,24,3);
    CustomDate cd;
    cd = dt;
    cd.display();
    dispdate(dt);
    Tester ts(dt);
    ts.display();
    cd = rtndate();
    cd.display();
    return 0;
    }
    六、顯式構(gòu)造函數(shù)
    注意上面Tester類的構(gòu)造函數(shù)前面有一個explicit修飾符。如果不加上這個關(guān)鍵字,那么在需要把CustomDate對象轉(zhuǎn)換成Tester對象時,編譯器會把該函數(shù)當(dāng)作轉(zhuǎn)換構(gòu)造函數(shù)來調(diào)用。但是有時候,并不想把這種只有一個參數(shù)的構(gòu)造函數(shù)用于轉(zhuǎn)換目的,而僅僅希望用它來顯式地初始化對象,此時,就需要在構(gòu)造函數(shù)前加explicit。如果在聲明了Tester對象以后使用了下面的語句將導(dǎo)致一個錯誤:
    ts=jd; //error
    這個錯誤說明,雖然Tester類中有一個以Date型變量為參數(shù)的構(gòu)造函數(shù),編譯器卻不會把它看作是從Date到Tester的轉(zhuǎn)換構(gòu)造函數(shù),因?yàn)樗穆暶髦邪薳xplicit修飾符。
    七、表達(dá)式內(nèi)部的轉(zhuǎn)換
    在表達(dá)式內(nèi)部,如果發(fā)現(xiàn)某個類型和需要的不一致,就會發(fā)生錯誤。數(shù)字類型的轉(zhuǎn)換是很簡單,這里就不舉例了。下面的程序是把Date對象轉(zhuǎn)換成長整型值。
    #include iostream.h
    class Date
    {
    int mo, da, yr;
    public:
    Date(int m,int d,int y)
    {
    mo=m; da=d; yr=y;
    }
    operator long();
    };
    Date::operator long()
    {
    static int dys[]={31,28,31,30,31,30,31,31,30,31,30,31};
    long days=yr;
    days*=365;
    days+=(yr-1900)/4; //從1900年1月1日開始計算
    for(int i=0;i days+=da;
    return days;
    }
    int main()
    {
    Date today(12,24,2003);
    const long ott=123;
    long sum=ott+today;
    cout< return 0;
    }
    在表達(dá)式中,當(dāng)需要轉(zhuǎn)換的對象可以轉(zhuǎn)換成某個數(shù)字類型,或者表達(dá)式調(diào)用了作用于某個類的重載運(yùn)算符時,就會發(fā)生隱式轉(zhuǎn)換。運(yùn)算符重載以后再學(xué)習(xí)。