最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++設計模式之CRTP的使用

 更新時間:2023年10月18日 14:09:34   作者:思想覺悟  
CRTP全稱是curious?recurring?template?pattern,即奇異遞歸模版模式,是一種c++的設計模式,精巧地結(jié)合了繼承和模板編程的技術(shù),下面就跟隨小編一起來學習一下CRTP的使用吧

什么是CRTP

CRTP全稱是curious recurring template pattern,即奇異遞歸模版模式,是一種c++的設計模式,精巧地結(jié)合了繼承和模板編程的技術(shù)??梢杂脕斫oc++的class提供額外功能、實現(xiàn)靜態(tài)多態(tài)等。

在CRTP之前只聽說C++通過指針實現(xiàn)了動態(tài)多態(tài),現(xiàn)在居然搞出了一個靜態(tài)多態(tài)的東西出來?不得不感慨C++真是一門高深莫測的語言...

動態(tài)多態(tài)

在了解靜態(tài)多態(tài)之前我們先來回顧一下動態(tài)多態(tài),C++ 通過類的繼承與虛函數(shù)的動態(tài)綁定,實現(xiàn)了多態(tài)。這種特性,使得我們能夠用基類的指針,訪問子類的實例。

#include <iostream>

class Animal{
public:
    // 注意需要添加virtual關(guān)鍵字
    virtual void run(){
        std::cout << "Animal run" << std::endl;
    }
};

class Cat:public Animal{
public:
    void run() override{
        std::cout << "Cat run" << std::endl;
    }
};

int main() {
    std::vector<Animal> animalVec;
    animalVec.emplace_back(Animal());
    // 非指針的形式,其實內(nèi)部調(diào)用的還是Animal的run
    animalVec.emplace_back(Cat());
    for (auto animal:animalVec) {
        animal.run();
    }
    // 動態(tài)多態(tài)需要通過指針的形式實現(xiàn)
    std::vector<Animal*> animalVecPtr;
    animalVecPtr.push_back(new Animal());
    animalVecPtr.push_back(new Cat());
    for (auto animal:animalVecPtr) {
        animal->run();
    }
    return 0;
}

CRTP的一個重要功能就是用來實現(xiàn)靜態(tài)多態(tài),CRTP在編譯階段就將子類類型以模版的形式傳遞到父類,以便在編譯階段實現(xiàn)多態(tài)性,這就是靜態(tài)多態(tài)。

既然有了動態(tài)多態(tài),為什么還需要靜態(tài)多態(tài)呢?答案是精益求精,為了效率而生...

我們知道動態(tài)多態(tài)是基于虛函數(shù)的形式在運行時進行動態(tài)綁定的,因此每次運行時都需要查詢虛函數(shù)表,所以動態(tài)綁定會降低程序的執(zhí)行效率。 為了兼顧多態(tài)與效率,就提出了CRTP。

CRTP的使用

我們先來看看在cppreference中是如何使用CRTP的

下面我們依然使用上面Animal的例子通過CRTP的方式實現(xiàn)靜態(tài)多態(tài)。

首先我們按照官方的例子,依瓢畫葫蘆:

#include <iostream>

template  < class T >
class Animal{
public:
    virtual ~Animal(){

    };
    // CRTP這里已經(jīng)不需要使用virtual關(guān)鍵字了
     void run(){
        (static_cast<T*>(this))->run();
    }
};

class Cat:public Animal<Cat>{
public:
    void run(){
        std::cout << "Cat run" << std::endl;
    }
};

class Dog:public Animal<Dog>{
public:
    void run(){
        std::cout << "Dog run" << std::endl;
    }
};

int main() {
    Animal<Cat>* cat = new Cat;
    cat->run();
    delete cat;
    Animal<Dog>* dog = new Dog;
    dog->run();
    delete dog;
    return 0;
}

程序運行起來后打印如下:

可以發(fā)現(xiàn)通過CRTP我們不使用關(guān)鍵字virtual也能實現(xiàn)了通過父類指針調(diào)用子類方法效果,這就是靜態(tài)多態(tài)的優(yōu)點,它比動態(tài)多態(tài)更高效,更安全。

通過上面的例子我們總結(jié)一下使用CRTP的三個重要步驟:

  • 繼承自模版類,因為用到了繼承,因此析構(gòu)函數(shù)需要用virtual修飾,以避免內(nèi)存泄露。
  • 子類將自身通過模板參數(shù)傳遞給父類。
  • 父類通過static_cast關(guān)鍵字將模板參數(shù)靜態(tài)轉(zhuǎn)化成子類,然后調(diào)用子類的鴨子模型方法。

一般來說將父類轉(zhuǎn)換成子類一般使用的是dynamic_cast,而CRTP是在編譯期間就已經(jīng)明確知道了子類的具體類型,因此直接使用static_cast更為高效。 這也正是CRTP這種設計的一大精髓。

通過仔細對比我們動態(tài)多態(tài)和靜態(tài)多態(tài)的兩個例子我們發(fā)現(xiàn)還是有點不一樣的,我們在動態(tài)多態(tài)中將Animal的指針添加到了std::vector中去,那么我們的CRTP能否也這樣做呢? 我們來試一下:

#include <iostream>

template<class T>
class Animal {
public:
    virtual ~Animal() {

    };
    // CRTP這里已經(jīng)不需要使用virtual關(guān)鍵字了
    void run() {
        (static_cast<T *>(this))->run();
    }
};

class Cat : public Animal<Cat> {
public:
    void run() {
        std::cout << "Cat run" << std::endl;
    }
};

class Dog : public Animal<Dog> {
public:
    void run() {
        std::cout << "Dog run" << std::endl;
    }
};

int main() {
    std::vector<Animal<Cat>*> animalVec;
    animalVec.emplace_back(new Cat());
    // 報錯了,因為vector存放的數(shù)據(jù)類型是Animal<Cat>
    animalVec.emplace_back(new Dog());
    for (auto animal: animalVec) {
        animal->run();
    }
    return 0;
}

我們發(fā)現(xiàn)報錯了,因為Animal和Animal不是同樣的數(shù)據(jù)類型,不能同時放入同一個vector中去。 既然問題的根源是他們不是同樣的數(shù)據(jù)類型,那么我們將它們變成同樣的數(shù)據(jù)類型不就是行了嗎?那么怎么把它們變成同樣的數(shù)據(jù)類型呢?

讓它們繼承一個共同的基類即可。這樣就是動態(tài)多態(tài)與靜態(tài)多態(tài)結(jié)合使用的例子了。

實例代碼如下:

#include <iostream>

class BaseAnimal {
public:
    virtual ~BaseAnimal() {

    };

    virtual void run() = 0;
};

template<class T>
class Animal: public BaseAnimal{
public:
    virtual ~Animal() {

    };
    // CRTP這里已經(jīng)不需要使用virtual關(guān)鍵字了
    void run() override{
        (static_cast<T *>(this))->run();
    }
};

class Cat : public Animal<Cat> {
public:
    void run() override {
        std::cout << "Cat run" << std::endl;
    }
};

class Dog : public Animal<Dog> {
public:
    void run() override {
        std::cout << "Dog run" << std::endl;
    }
};

int main() {
    std::vector<BaseAnimal*> animalVec;
    animalVec.emplace_back(new Cat());
    // 報錯了,因為vector存放的數(shù)據(jù)類型是Animal<Cat>
    animalVec.emplace_back(new Dog());
    for (auto animal: animalVec) {
        animal->run();
    }
    return 0;
}

這樣一來,我們通過CRTP與虛函數(shù)結(jié)合,即保留了動態(tài)多態(tài)的各種特性,也減少了部分虛函數(shù)的查找開銷。

到此這篇關(guān)于C++設計模式之CRTP的使用的文章就介紹到這了,更多相關(guān)C++設計模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • Visual?Studio調(diào)試技巧與函數(shù)遞歸示例詳解

    Visual?Studio調(diào)試技巧與函數(shù)遞歸示例詳解

    在Visual Studio(VS)中調(diào)試程序是開發(fā)過程中非常重要的一環(huán),它能幫助你發(fā)現(xiàn)并修復代碼中的錯誤,這篇文章主要介紹了Visual?Studio調(diào)試技巧與函數(shù)遞歸的相關(guān)資料,需要的朋友可以參考下
    2025-08-08
  • C語言中 type *(0)的具體使用

    C語言中 type *(0)的具體使用

    表達式?type * (0)?在 C/C++ 編程中是一個常見的技巧,通常用于內(nèi)核編程和一些系統(tǒng)編程場景中,本文主要介紹了C語言中 type *(0)的具體使用,感興趣的可以了解一下
    2024-08-08
  • c++中數(shù)字與字符串之間的轉(zhuǎn)換方法(推薦)

    c++中數(shù)字與字符串之間的轉(zhuǎn)換方法(推薦)

    下面小編就為大家?guī)硪黄猚++中數(shù)字與字符串之間的轉(zhuǎn)換方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • C語言多媒體框架GStreamer使用教程深講

    C語言多媒體框架GStreamer使用教程深講

    GStreamer 是用來構(gòu)建流媒體應用的開源多媒體框架(framework),其目標是要簡化音/視頻應用程序的開發(fā),已經(jīng)能夠被用來處理像 MP3、Ogg、MPEG1、MPEG2、AVI、Quicktime 等多種格式的多媒體數(shù)據(jù)
    2022-07-07
  • C語言解字符串逆序和單向鏈表逆序問題的代碼示例

    C語言解字符串逆序和單向鏈表逆序問題的代碼示例

    這篇文章主要介紹了C語言解字符串逆序和單向鏈表逆序問題的代碼示例,求逆序也是考研和面試中的基礎算法題類型,需要的朋友可以參考下
    2016-06-06
  • C++超詳細講解單鏈表的實現(xiàn)

    C++超詳細講解單鏈表的實現(xiàn)

    單鏈表是后面要學的雙鏈表以及循環(huán)鏈表的基礎,要想繼續(xù)深入了解數(shù)據(jù)結(jié)構(gòu)以及C++,我們就要奠定好這塊基石!接下來就和我一起學習吧
    2022-03-03
  • C語言指針的長度和類型深入分析

    C語言指針的長度和類型深入分析

    這篇文章主要介紹了C語言指針的長度和類型,針對常見的各個類型進行了相對詳細的分析,需要的朋友可以參考下
    2014-09-09
  • C++入門語法之函數(shù)重載詳解

    C++入門語法之函數(shù)重載詳解

    這篇文章主要為大家詳細介紹了C++入門語法之函數(shù)重載,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • C++ 單例模式的詳解及實例

    C++ 單例模式的詳解及實例

    這篇文章主要介紹了C++ 單例模式的詳解及實例的相關(guān)資料,這里對單例中的懶漢模式和餓漢模式進行實現(xiàn)和比較,需要的朋友可以參考下
    2017-07-07
  • C++ 中 const 和 static 關(guān)鍵字用法及定義

    C++ 中 const 和 static 關(guān)鍵字用法及定義

    本文給大家介紹C++中const和static 關(guān)鍵字用法及定義,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2025-09-09

最新評論

闽侯县| 鄂尔多斯市| 汝城县| 罗源县| 伊宁市| 凯里市| 独山县| 资溪县| 克拉玛依市| 长春市| 云阳县| 深州市| 定南县| 琼海市| 类乌齐县| 南召县| 杨浦区| 景泰县| 兰溪市| 攀枝花市| 柘城县| 株洲市| 台前县| 黄梅县| 兴山县| 美姑县| 伊川县| 长兴县| 顺平县| 延长县| 达孜县| 福州市| 体育| 青铜峡市| 延长县| 开封市| 和林格尔县| 炉霍县| 河曲县| 丘北县| 汾西县|