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

        ?

        如何理解C++模板

        2014-02-25 02:03:46蘇子偉
        軟件工程 2014年2期
        關(guān)鍵詞:基類編譯器代碼

        蘇子偉

        首先談一下什么是模板。模板就是為解決某一類問題,從而抽象了這類問題的具體共性,為這類問題提供一種通用的解決方法。工作中有很多這樣的例子,比如我們熟知的Microsoft Office中的模板,它給我們的工作帶來(lái)了很多便利,改變了每件事都得從頭編碼的做事方法,使得代碼重用變得如此簡(jiǎn)單。

        C++模板的基礎(chǔ)討論

        C++模板的思想也是基于此,它抽象了具體的型別,實(shí)現(xiàn)了共性邏輯,為一類問題提供了統(tǒng)一的泛型接口。模板機(jī)制使得編程者在定義類和函數(shù)時(shí)能以類型作為參數(shù),并且模板只依賴于實(shí)際使用時(shí)的傳入?yún)?shù),不關(guān)心能被用作參數(shù)的那些不同類型之間的任何聯(lián)系。剛剛接觸C++模板時(shí),可能會(huì)感覺它不就是C的#define宏嗎,只是在這里換了一種說(shuō)法,無(wú)非是“新瓶裝舊酒”啊。但是如果你對(duì)它感興趣,再深入地理解一下,相信它會(huì)帶給你很大的驚喜的。當(dāng)前,C++模板已經(jīng)變成了通用編程的基礎(chǔ),是標(biāo)準(zhǔn)模板庫(kù)(STL)的基石。它使得用戶接口更簡(jiǎn)單,表達(dá)更清晰。

        C++是一門靜態(tài)的語(yǔ)言,它是強(qiáng)類型檢查的,所以代碼不可能在運(yùn)行時(shí)再編譯生成。而C++模板的技術(shù)核心也在于編譯期的代碼解釋和執(zhí)行期的零成本。雖然這點(diǎn)同#define宏比較類似,但是它實(shí)現(xiàn)更簡(jiǎn)單,更不容易產(chǎn)生錯(cuò)誤,使得代碼看起來(lái)更具美感,并且它提供函數(shù)返回值,可以進(jìn)行代碼調(diào)試,可以進(jìn)行編譯期的變量類型檢查等等,這些都不是#define宏能比擬的。下面讓我們先看一下C++中如何定義一個(gè)模板。

        怎么去定義一個(gè)模板

        C++中有兩種模板,一種是類模板,一種是函數(shù)模板,函數(shù)模板也可以在類模板中使用。因?yàn)槟0迨蔷幾g期生成代碼的,所以一般我們都把模板代碼放到一個(gè)頭文件中聲明定義。首先,我們看一下類模板。

        template class ClassName

        {

        enum { ssize = 50 };

        T m_Stack[ssize];

        intm_Top_postion;

        public:

        ClassName () :m_Top_postion(0) { }

        voidpush_into(const T& i){

        m_Stack[m_Top_postion++] = i;

        }

        T pop_up() {

        returnm_Stack[--m_Top_postion];

        }

        int size(){

        returnm_Top_postion;

        }

        };

        template這個(gè)關(guān)鍵字告知編譯器,隨后的類定義ClassName將需要一個(gè)或更多的類型。這里的T是需要替換的類型參數(shù),你可以指定T為任何你所需要的有意義的類型,比如整型、結(jié)構(gòu)體類型,或者是一個(gè)模板類型等。(關(guān)于類模板中的常量以及詳細(xì)的模板的語(yǔ)法,請(qǐng)參照C++語(yǔ)言程序設(shè)計(jì)者BjarneStroustrup的大作《C++程序設(shè)計(jì)語(yǔ)言》)

        其次,是函數(shù)模板。它用于創(chuàng)建基于泛型為參數(shù)的函數(shù)。

        templateintGetsize(std::vector&param);

        這里的template和class的意義同類模板的一樣。但是在函數(shù)模板中模板參數(shù)必須出現(xiàn)在函數(shù)參數(shù)中。

        模板的實(shí)例化

        C++模板提供了對(duì)源代碼重用的方法,而不像是繼承跟組合提供的對(duì)目標(biāo)代碼的重用方式。這使得處理問題的耦合更小,更簡(jiǎn)單,接口更加豐富,代碼量更少。編譯器會(huì)根據(jù)具體的參數(shù),生成具體問題的解法的特定代碼,這就是模板的實(shí)例化。下面讓我們通過(guò)一個(gè)例子來(lái)認(rèn)識(shí)一下模板代碼是怎么生成具體的特定代碼的。

        template class ClassName {

        T m_data[size];

        intm_pos;

        public:

        ClassName () :m_pos(0) { }

        voidput_into(const T& t)

        {

        m_data[m_pos++] = t;

        }

        };

        下面我們定義一個(gè)變量ClassName v;,在這里T的類型變?yōu)閕nt,整形參數(shù)size沒有改變而是使用了模板中的默認(rèn)值60。這樣編譯器產(chǎn)生的類代碼如下。

        classClassName {

        intm_data[60];

        intm_pos;

        public:

        ClassName () :m_pos(0) { }

        voidput_into(const T& t)

        {

        m_data[m_pos++] = t;

        }

        };

        這就是模板參數(shù)的實(shí)例化過(guò)程,根據(jù)不同的參數(shù)生成了特定的類。函數(shù)模板的原理同類模板相同,這里就不在贅述了。

        模板的特化

        一個(gè)模板描述了某個(gè)范圍內(nèi)的一族函數(shù)或類。當(dāng)給定模板參數(shù)時(shí),這些模板參數(shù)決定了這一族函數(shù)或類中的獨(dú)一無(wú)二的特例,這樣的過(guò)程結(jié)果被稱為特化。當(dāng)然模板實(shí)例化也是特化的過(guò)程。特化分為全特化和半特化,但是函數(shù)模板不能半特化,必須一次性的全特化。下面我們分別看看這兩中情況。

        首先看看全特化,全特化使用了template<>來(lái)標(biāo)識(shí)。

        templateconst T& compare(const T& a, const T& b) {

        return (a > b) ? a : b;

        }

        // An explicit specialization of the max template

        template<>

        const char* const& compare(const char* const& a, const char* const& b) {

        return (strlen(a) >strlen(b)) ? a : b;

        }

        這樣我們使用模板時(shí),例如compare<>(s1,s2)就是使用全特化后的模板生成的最終代碼。compare(4,5)就是使用未全特化的模板生成的最終代碼。

        再看一個(gè)例子:

        template class CAssert;

        template<> class CAssert{};

        在這個(gè)例子中實(shí)現(xiàn)的部分跟省略的一樣多,但是它可以工作得很好。它的全特化只是實(shí)現(xiàn)了bool型別為true的情況,這樣我們就能使用它在代碼中進(jìn)行靜態(tài)斷言。

        再來(lái)看一下半特化,半特化又叫偏特化。這種特化方式只是針對(duì)于類模板。故名思議,半特化只是部分地特化了模板,約束了符合用戶期望的行為的模板參數(shù),其他參數(shù)仍然維持其泛型的性質(zhì)。編譯器在生成模板代碼時(shí)會(huì)查找出最匹配的定義,來(lái)進(jìn)行實(shí)例化。模板的半特化有很多巧妙的應(yīng)用,它很好地處理了一些分支問題。下面就以loki庫(kù)中的一個(gè)例子來(lái)看看這種迷人的用法。

        比如你需要向一個(gè)容器里面插入變量,有時(shí)是T,有時(shí)是T*。Loki庫(kù)的實(shí)現(xiàn)如下。

        template

        struct Select

        {

        Typedef T result;

        };

        template

        struct Select

        {

        TypedefU result;

        };

        Select::result即為需要的型別,只需要根據(jù)boolval的值決定。

        模板的遞歸模式

        這種模板的遞歸方式能使得每個(gè)派生類都派生于一個(gè)唯一的基類,這個(gè)基類使用了它本身作為模板參數(shù)。從理論上來(lái)說(shuō)這會(huì)產(chǎn)生無(wú)休止的遞歸循環(huán),使得編譯器無(wú)法推斷出派生類及其基類的具體的型別大小等,但是只要基類中的數(shù)據(jù)成員不含有與模板型別相關(guān)的依賴,模板是可以被實(shí)例化出來(lái)的。當(dāng)程序設(shè)計(jì)者需要派生類具有某些性質(zhì),但是這些性質(zhì)的實(shí)現(xiàn)通過(guò)繼承又不能很好的處理時(shí),此時(shí)可以考慮模板的遞歸模式。下面我們看一下具體的例子。

        template class Counted {

        staticsize_t count;

        public:

        Counted() { ++count; }

        Counted(const Counted&) { ++count; }

        ~Counted() { --count; }

        staticsize_tgetCount() { return count; }

        };

        templatesize_t Counted::count = 0;

        // children class definitions

        classClass1 : public Counted {};

        classClass2 : public Counted {};

        這樣我們的子類都繼承了唯一的基類,并且基類的型別參數(shù)就是其自身。

        模板的特征和策略

        特征(traits)提供了類或類模板的類型接口,而策略(policy)提供了類或類模板的函數(shù)接口。特征和策略被大量地應(yīng)用到了STL標(biāo)準(zhǔn)模板庫(kù),通過(guò)對(duì)策略的組合應(yīng)用,可以使得同一個(gè)模板類產(chǎn)生出無(wú)與倫比的構(gòu)建能力,從而涵蓋更多的信息,接口更通用。

        下面看一個(gè)具體的例子。

        #include

        #include

        class cat {

        public:

        friendstd::ostream& operator<<(std::ostream&os, const cat&) {

        returnos<< "cat!";

        }

        };

        class dog {

        public:

        friendstd::ostream& operator<<(std::ostream&os, const dog&) {

        returnos<< "dog!";

        }

        };

        class Johnson {

        public:

        friendstd::ostream& operator<<(std::ostream&os, const Johnson&) {

        returnos<< "Johnson";

        }

        };

        class Tom {

        public:

        friendstd::ostream& operator<<(std::ostream&os, const Tom&) {

        returnos<< "Tom";

        }

        };

        template class PersonTraits;

        template<> class PersonTraits {

        public:

        typedef cat Favorite_thing;

        };

        template<> class PersonTraits {

        public:

        typedef dog Favorite_thing;

        };

        class dance {

        public:

        std::stringtodo() { return std::string(" loves to dance."); }

        };

        class sing {

        public:

        std::stringtodo() { return std::string(" loves to sing."); }

        };

        template>

        class family {

        person who;

        typedeftypename traits::Favorite_thingFavorite_thing;

        Favorite_thingfav;

        actlike_to_do;

        public:

        family(const person& p) : who(p) {}

        voidfavorite_thing() {

        std::cout<< who <<" loves " <

        }

        };

        int main()

        {

        Johnson John;

        family fam1(John);

        fam1.favorite_thing();

        Tom tom;

        family fam2(tom);

        fam2.favorite_thing();

        }

        這里面特征就是PersonTraits類里面的Favorite_thing,而策略就是todo()函數(shù)。這里我們能夠看到,當(dāng)把策略組合使用時(shí),就是它們最有用的時(shí)候了。程序接口的使用者可以借由組合不同的策略來(lái)實(shí)現(xiàn)自己需要的高階行為。建立策略類最重要的部分就是如何正確地分解策略。一般來(lái)說(shuō)建立好的策略類,必須遵守的前提就是這些策略類必須是正交的。這樣這些策略類彼此之間是不會(huì)產(chǎn)生耦合的。在我們?cè)O(shè)計(jì)類的時(shí)候,我們也應(yīng)該考慮,某個(gè)機(jī)能如果有一個(gè)以上的解決方法,就應(yīng)該考慮把該機(jī)能移出來(lái),做成一個(gè)策略。這樣我們就不會(huì)把大量的精力花在維護(hù)龐大的代碼上了。

        由于篇幅有限,本文只是討論了C++模板的部分知識(shí),還有很多有趣的應(yīng)用等待我們?nèi)グl(fā)掘,C++模板的開發(fā)與應(yīng)用已經(jīng)進(jìn)入了一個(gè)全新之境。

        猜你喜歡
        基類編譯器代碼
        基于C#面向?qū)ο蟪绦蛟O(shè)計(jì)的封裝、繼承和多態(tài)分析
        基于相異編譯器的安全計(jì)算機(jī)平臺(tái)交叉編譯環(huán)境設(shè)計(jì)
        創(chuàng)世代碼
        創(chuàng)世代碼
        創(chuàng)世代碼
        創(chuàng)世代碼
        空戰(zhàn)游戲設(shè)計(jì)實(shí)例
        一種基于用戶興趣的STC改進(jìn)算法
        虛機(jī)制在《面向?qū)ο蟪绦蛟O(shè)計(jì)C++》中的教學(xué)方法研究
        通用NC代碼編譯器的設(shè)計(jì)與實(shí)現(xiàn)
        乌克兰粉嫩xxx极品hd| 国产av一区二区日夜精品剧情| 精品福利一区二区三区| 黑人老外3p爽粗大免费看视频| 亚洲精品国产一区二区免费视频| 日韩少妇人妻中文字幕| 麻豆一区二区三区蜜桃免费| 国产高潮国产高潮久久久| 免费黄网站久久成人精品| 中文字幕这里都是精品| 国产高清不卡在线视频| 亚洲视频在线免费不卡| 国产乱人偷精品人妻a片| 色综合久久精品亚洲国产| 欧美成年黄网站色视频| 中文无码日韩欧免费视频| 国产内射视频在线播放| 亚洲一区二区懂色av| 手机在线免费观看av不卡网站| 老师开裆丝袜喷水视频| 日产无人区一线二线三线乱码蘑菇| 韩国三级中文字幕hd久久精品| 国产精品国产三级国产an | 国产乱人伦偷精品视频| 综合五月网| 中文字幕avdvd| 久天啪天天久久99久孕妇| 亚洲色图第一页在线观看视频| 国产精品亚洲精品一区二区| 日韩精品在线免费视频| 久久婷婷色香五月综合缴缴情| 2020年国产精品| 国产xxxx99真实实拍| 亚洲一区二区在线视频播放| 麻豆夫妻在线视频观看| 久久综合精品人妻一区二区三区| 精品无码国产自产拍在线观看蜜 | 末发育娇小性色xxxxx视频| 国内精品一区二区三区| 国产91精品丝袜美腿在线| 麻豆国产精品一区二区三区|