亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        從C基本順序表到C++基本順序表類

        2008-12-31 00:00:00王立柱
        計算機(jī)教育 2008年11期

        在上一期的“數(shù)組和基本順序結(jié)構(gòu)”一文中我們講到,優(yōu)秀的程序員自覺地把函數(shù)分為基本操作函數(shù)和應(yīng)用函數(shù),然后把基本操作函數(shù)和基本順序表結(jié)構(gòu)看作一個整體,當(dāng)作一個類型,用于應(yīng)用函數(shù)即程序的設(shè)計和實現(xiàn),表1簡要概括了這些內(nèi)容。

        可是C語言編譯器沒有把這兩類函數(shù)區(qū)別開,它們的聲明、定義和調(diào)用方式都一樣。不僅如此,它們對結(jié)構(gòu)成員的訪問權(quán)限也一樣,應(yīng)用程序可以直接訪問結(jié)構(gòu)成員,例如表1中的Purge函數(shù)可以修改為:

        void Purge(SeqList *L)

        //刪除表中的重復(fù)數(shù)據(jù)

        {

        int i,j;

        for(i=0;i<L->size;i++)//直接訪問結(jié)構(gòu)成員size

        {

        j=i+1;

        while(j<L->size)

        if(L->data[i]==L->data[j]) //直接訪問結(jié)構(gòu)成員data

        Erase(L,j);

        else

        j++;

        }

        }

        而C++編譯器克服了C的局限性,實現(xiàn)程序員的設(shè)計方法,從概念和語法兩個方面把兩類函數(shù)區(qū)分開來。

        1.從C基本順序表到C++基本順序表類的轉(zhuǎn)換

        下面我們分十步把表1中簡化的C基本順序表結(jié)構(gòu)轉(zhuǎn)化為C++基本順序表類。

        ① 布爾型函數(shù)。C++增加了布爾型,它占用一個字節(jié),僅取兩個值:真和假(true和1),對應(yīng)的整型值是1和0。于是,對取真假值的函數(shù),應(yīng)將其返回值定義為布爾型。例如:

        bool ListEmpty(const SeqList *l);//判空

        ② 將宏常量改為const常量。例如將

        #define MaxSeqSize 100

        改為

        const int MaxSeqSize=100;

        在C++中一般都用const常量或者枚舉常量來代替宏常量,這是因為宏代表的是在預(yù)處理階段完成的一種文本替換過程,它忽略了語言的作用域、類型系統(tǒng)和所有其他的語言特性和規(guī)則,這使它和語言本身割裂開來。

        ③ 常量型引用調(diào)用。把帶有形式數(shù)據(jù)類型參量的值調(diào)用函數(shù)改為常量型引用調(diào)用[1]:

        void InsertRear(SeqList *l, const Type item);//尾插

        ④ 函數(shù)類型是常量型引用。若函數(shù)類型是形式數(shù)據(jù)類型,則將其改為常量型引用[1]:

        const Type GetData(const SeqList *l,int id);//取值

        ⑤ 重載。簡化求長和判空等函數(shù)名:

        int Size(const SeqList *l);//求長。取元素個數(shù)

        bool Empty(const SeqList *l);//判空

        在C語言中,函數(shù)名代表函數(shù)地址,因此不同的函數(shù)必須有不同的函數(shù)名,即使參數(shù)表不同而功能相同的函數(shù),也要賦予不同的函數(shù)名。例如,在基本順序表、基本順序隊列和基本順序棧中的求長基本操作,雖然功能一樣,但是函數(shù)名必須有別:

        int ListSize(const SeqList *l);//基本順序表求長

        int QSize(const Queue *q);//基本順序隊列求長

        int StSize(const Stack *s);//基本順序棧求長

        顯然,這給程序設(shè)計和閱讀帶來不必要的麻煩。按照簡約的習(xí)慣,功能相同的函數(shù),即使參數(shù)表不同,也應(yīng)具有相同的函數(shù)名,例如:

        int Size(const SeqList *l);//基本順序表求長

        int Size(const Queue *q);//基本順序隊列求長

        int Size(const Stack *s);//基本順序棧求長

        可是函數(shù)名相同而參數(shù)表不同的函數(shù)如何對應(yīng)不同的地址呢?一種簡單的方法是建立一個映射,使函數(shù)名和參數(shù)表對應(yīng)一個新的函數(shù)名。這個映射是單一的:只要函數(shù)名和參數(shù)表有一處不同,所對應(yīng)的新的函數(shù)名就不同。我們讓這個新的函數(shù)名對應(yīng)函數(shù)的地址,這項工作由C++編譯器來完成。它根據(jù)參量表的參量個數(shù)和類型對函數(shù)名進(jìn)行擴(kuò)展,形成函數(shù)的內(nèi)部名稱,這個內(nèi)部名稱對應(yīng)函數(shù)地址。例如,求長函數(shù)經(jīng)編譯器擴(kuò)展后的內(nèi)部名稱可能是:

        Size_const_SeqList*

        Size_const_Queue*

        Size_const_Stack*

        當(dāng)然,不同的編譯器,擴(kuò)展方法可能不同,但實質(zhì)相同。

        ⑥ 成員函數(shù)。首先,將構(gòu)造函數(shù)和基本操作函數(shù)參量表中的結(jié)構(gòu)指針l改名為this,例如:

        void SetList(SeqList *this);//給元素個數(shù)size賦值0

        int Size(const SeqList *this);//求長

        bool Empty(const SeqList *this);//判空

        const Type GetData(const SeqList *this,int id);

        //取值

        void InsertRear(SeqList *this, const Type item);

        //尾插

        void Delete(SeqList *this, int id);//定點刪除

        錯誤信息報告函數(shù)沒有結(jié)構(gòu)指針參量,需要補上(補上的this指針在定義中沒有用,我們稱它為啞元),然后將函數(shù)名簡化:

        void Error(const SeqList *this,const char *c);//錯誤信息報告

        接下來,將this指針隱藏,指向常量指針this的const修飾符移到參量表括號之后。最后,將構(gòu)造函數(shù)和基本操作函數(shù)放入結(jié)構(gòu)體內(nèi),成為結(jié)構(gòu)的成員,稱為成員函數(shù),后帶const修飾符的函數(shù)稱為常量型成員函數(shù):

        const int MaxSeqSize=100;

        struct SeqList

        {

        Type data[MaxSeqSize];

        int size;

        void SetList(void);//構(gòu)造函數(shù)

        int Size (void)const; //常量型成員函數(shù)

        bool Empty(void)const;

        void InsertRear(const Type item);

        const Type GetData(int id)const;//常量型成員函數(shù)

        void Erase(int id);

        void Error(const char *c)const; //常量型成員函數(shù)

        };

        成員函數(shù)的調(diào)用方式發(fā)生變化,設(shè)L為表結(jié)構(gòu)變量,原來是

        ListSize(L);//L基本順序表結(jié)構(gòu)變量

        Erase(L,1);

        現(xiàn)在是

        L.Size();

        L.Erase(1);

        設(shè)L為表結(jié)構(gòu)指針,原來是

        ListSize(L);

        //L基本順序表結(jié)構(gòu)變量指針

        Erase(L,1);

        現(xiàn)在是

        L->Size();

        L->Erase(1);

        C++編譯器對新的調(diào)用方式在內(nèi)部展開的過程與上面生成函數(shù)成員的過程正相反。例如:

        L.Size();

        內(nèi)部展開過程首先是顯示this指針參量,然后根據(jù)參量表擴(kuò)展函數(shù)名,擴(kuò)展之后,函數(shù)的內(nèi)部原型可以假設(shè)是

        int _ListSize(const SeqList*this);

        然后調(diào)用形式為:

        _ListSize(L);

        實質(zhì)上與原來相同,但是意義大不一樣:成員函數(shù)屬于結(jié)構(gòu)的成員,由結(jié)構(gòu)變量負(fù)責(zé)調(diào)用,而且成員函數(shù)中隱藏的this指針就指向那個調(diào)用它的結(jié)構(gòu)變量。

        原來一個結(jié)構(gòu)空間的大小是其數(shù)據(jù)成員空間大小之和,現(xiàn)在結(jié)構(gòu)中包含了函數(shù)成員,是否結(jié)構(gòu)空間就變大了?答案是沒有。從圖1演示的成員函數(shù)調(diào)用的內(nèi)部過程我們不難理解,新的結(jié)構(gòu)與原來的結(jié)構(gòu)本質(zhì)上是相同的,只是編譯器的工作多了,函數(shù)和調(diào)用有了內(nèi)部展開形式。

        ⑦ 成員函數(shù)定義。成員函數(shù)的定義可以在結(jié)構(gòu)體內(nèi),也可以在結(jié)構(gòu)體外。在結(jié)構(gòu)體內(nèi)定義,等于內(nèi)聯(lián)函數(shù);在結(jié)構(gòu)體外定義,等于函數(shù)類型標(biāo)識符和函數(shù)名之間要加入結(jié)構(gòu)名和域解析運算符“::”,以區(qū)別于一般的實用函數(shù)。在函數(shù)定義體內(nèi),this指針可以顯示,也可以隱藏。

        const int MaxSeqSize=100;

        struct SeqList

        {

        Type data[MaxSeqSize];

        int size;

        void SetList(void);

        int Size (void)const{return(size);}// return(this->size);

        //在結(jié)構(gòu)體內(nèi)定義

        bool Empty(void)const;

        ……

        };

        bool SeqList::Empty() const//在結(jié)構(gòu)體外定義

        {

        return(size==0);//return(this->size==0);

        }

        ⑧ 構(gòu)造函數(shù)?,F(xiàn)在從聲明、定義和調(diào)用三個方面把基本操作函數(shù)與實用功能函數(shù)區(qū)分開了,接下來我們區(qū)分構(gòu)造函數(shù)和基本操作函數(shù)。在基本順序表中,構(gòu)造函數(shù)的執(zhí)行過程是:

        Seqlis L;

        SetList(L);//調(diào)用構(gòu)造函數(shù)

        這兩條語句是不能分開的,它們一起完成了基本順序表的創(chuàng)建。C++把這兩條語句合并為一條。具體方法是:把構(gòu)造函數(shù)名和結(jié)構(gòu)名統(tǒng)一,都是SeqList,使語句

        Seqlis L;

        蘊涵著調(diào)用構(gòu)造函數(shù)。因為構(gòu)造函數(shù)是基本順序表定義的一部分,所以它的頭應(yīng)該是結(jié)構(gòu)名稱,不含返回值類型說明。又因為它的內(nèi)容需要程序員定義,所以保留了函數(shù)體。

        struct SeqList

        {……

        SeqList(void);//構(gòu)造函數(shù)聲明,名稱與結(jié)構(gòu)名稱相同,而且取消了函數(shù)返回值類型

        ……

        };

        SeqList::SeqList (void)//構(gòu)造函數(shù)外部定義

        {

        size=0;//this->size=0;

        }

        ⑨ 訪問權(quán)限。在基本順序表中,各種函數(shù)都可以直接訪問結(jié)構(gòu)成員,沒有區(qū)別。C++在結(jié)構(gòu)中增加了訪問權(quán)限,一般分私有和公有。私有成員只能由結(jié)構(gòu)成員訪問,即對結(jié)構(gòu)成員公開,而結(jié)構(gòu)以外的函數(shù)只能訪問公有成員。公有部分是任何函數(shù)都可以直接訪問或使用的,即對外公開、可見。

        const int MaxSeqSize=100;

        struct SeqList

        {

        private://私有聲明

        Type data[MaxSeqSize];

        int size;

        void Error(const char *c)const;//私有函數(shù)

        public://公有聲明

        SeqList(void);//構(gòu)造函數(shù)

        int Size (void)const;

        bool Empty(void)const;

        void InsertRear(const Type item);

        const Type GetData(int id)const;

        void Erase(int id);

        };

        結(jié)構(gòu)以外的函數(shù)“看不見”結(jié)構(gòu)中的私有部分。例如,實用功能函數(shù)Purge是不能直接訪問結(jié)構(gòu)成員data、size和Error,只能通過公有成員函數(shù)來處理:

        void Purge(SeqList *L)

        //刪除表中的重復(fù)數(shù)據(jù)

        {

        int i,j;

        for(i=0;i<L->Size();i++)

        {

        j=i+1;

        while(j<L->Size())

        if(L->GetData(i)==L->GetData(j))

        L->Erase(j);

        else

        j++;

        }

        }

        ⑩ new和delete運算符。構(gòu)造函數(shù)的調(diào)用屬于順序表定義語句的一部分,意義是:誰創(chuàng)建順序表空間,誰就負(fù)責(zé)調(diào)用構(gòu)造函數(shù)給空間賦初值。這時,原有的動態(tài)分配函數(shù)malloc就不實用了。下面通過表2的對比來認(rèn)識新的運算符new和delete。

        與malloc不同,new負(fù)責(zé)調(diào)用構(gòu)造函數(shù)。與free不同,delete釋放動態(tài)數(shù)組空間要加下標(biāo)運算符“[]”。

        結(jié)構(gòu)體包含成員函數(shù)之后,其關(guān)鍵字struct通常換為class,稱為類,也可以沿用struct。它們的差別主要是:類(class)的默認(rèn)項是私有的,在類中,私有成員的說明符private可以省略;而結(jié)構(gòu)(struct)的默認(rèn)項是公有的,公有成員的說明符public可以省略。何時用結(jié)構(gòu),何時用類?一般程序員的做法是:僅含公共數(shù)據(jù)成員,不含接口(即成員函數(shù))時,采用結(jié)構(gòu),應(yīng)用程序看到的即為數(shù)據(jù)成員的實際格式;否則采用類,數(shù)據(jù)成員的實際格式對外是不可見的、封裝的,是可以改造的,應(yīng)用程序只能通過接口(即公有成員函數(shù))來操作數(shù)據(jù)成員。例如:

        struct Student//結(jié)構(gòu)

        {

        long ID;float g;//ID表示學(xué)號,g表示成績

        };

        class SeqList//類

        {

        private://私有聲明(可以省略)

        Type data[MaxSeqSize];

        int size;

        void Error(const char *c)const;//私有函數(shù)

        public://公有聲明

        SeqList(void);//構(gòu)造函數(shù)

        ……

        };

        由類定義的變量通常稱為對象。類的成員函數(shù)也稱為方法,而且成員函數(shù)只能通過類的對象來調(diào)用。我們說基于對象的程序設(shè)計,就包含了這一層意思。例如:

        L.Erase(1);//對象L調(diào)用成員函數(shù)Erase,刪除第2個數(shù)據(jù)元素

        但是,不能用這種方式調(diào)用構(gòu)造函數(shù),即

        L.SeqList();//非法

        因為構(gòu)造函數(shù)是用來創(chuàng)建對象的,此時L還不是也不能是對象。

        2C++基本順序表類的聲明和實現(xiàn)

        前面我們通過變換引入了C++順序表類,表3和表4分別對比了C++基本順序表類和C基本順序表結(jié)構(gòu)的聲明和實現(xiàn),表5對比了C++基本順序表類應(yīng)用程序和C基本順序表結(jié)構(gòu)應(yīng)用程序。

        參考文獻(xiàn)

        [1] 王立柱. C/C++與數(shù)據(jù)結(jié)構(gòu)(第3版)(上冊)[M]. 北京: 清華大學(xué)出版社, 2008.214,216.

        蜜桃视频永久免费在线观看| 一道久在线无码加勒比| 久久免费大片| 按摩女内射少妇一二三区| 亚洲国产中文字幕一区| 久久精品国产亚洲av无码娇色 | 三上悠亚免费一区二区在线| 麻豆av一区二区天堂| 国产精品成人自拍在线观看| 国产一区二区三区在线电影| 国内精品九九久久久精品| 久久国产精品男人的天堂av| 少妇太爽了在线观看免费| 狠狠色综合7777久夜色撩人| 国产精品无需播放器| 亚洲一区极品美女写真在线看| 亚洲高清国产一区二区| 国产午夜精品一区二区三区| 欧美日韩国产一区二区三区地区| 狼人综合干伊人网在线观看| 国产精品白浆免费观看| 国产91会所女技师在线观看| 亚洲乱码日产精品一二三| 国产喷水福利在线视频| 日韩熟女一区二区三区| 中文字幕一区二区精品视频| 欧美金发尤物大战黑人| 四虎影视久久久免费| 人妻中文字幕一区二区二区| 美女视频在线观看网址大全| 亚洲va久久久噜噜噜久久男同| 日韩在线看片| 在线观看视频国产一区二区三区| 欧美老熟妇乱xxxxx| 无码熟熟妇丰满人妻啪啪| 日产精品一区二区三区免费| 人妻少妇不满足中文字幕| 久久综合精品国产一区二区三区无码| 亚洲是图一区二区视频| 情av一区二区三区在线观看| 亚洲成在人线av品善网好看|