C++ template隨筆

来源:http://www.cnblogs.com/kentax/archive/2016/01/30/5159035.html
-Advertisement-
Play Games

話題從重用開始說起: 最基本的重用,重用一個方法,被重用的邏輯被抽取封裝成為方法,之後我們把方法當成一種工具來使用(處理數據,輸入輸出,或者改變狀態)。 來到了面向對象的時代,如果這個方法出現父類上面就是繼承,如果這個方法出現在其他對象上就是代理,如果子類想要重用父類的介面又不想重用實現那麼就是多態


話題從重用開始說起:

最基本的重用,重用一個方法,被重用的邏輯被抽取封裝成為方法,之後我們把方法當成一種工具來使用(處理數據,輸入輸出,或者改變狀態)。

來到了面向對象的時代,如果這個方法出現父類上面就是繼承,如果這個方法出現在其他對象上就是代理,如果子類想要重用父類的介面又不想重用實現那麼就是多態。

但是這些重用都是基於相同的數據類型,方法創建出來後接收參數都是固定的類型,對於多態,可以通過子類來實現不同行為,但是方法總歸還是接收一個固定父類型(或者介面)參數。

想想有沒有這樣的需求,兩個完全不同的類型,他們之間不存在繼承關係,但是卻需要同樣的處理邏輯,比如說各種類型都需要排序,比如說各種類型都有集合處理的需求。

那麼能不能讓方法接收不同類型來實現重用呢?C++的Template就是解決這樣問題。

 

模板方法

既然這樣需求不同類型卻需要相同處理方法,所以有了模板方法,

template<typename T>
T Add(T a, T b)
{
    return a + b;
};

int main()
{
    string s1 = "Hello";
    string s2 = "World";
    cout << Add(12,13) << endl;
    cout << Add(s1,s2) << endl;
    return 0;
}; 輸出: 25 HelloWorld

 模板類

方法都能模板化,那麼類怎麼能夠不模板化, 作為面向對象的C++,所以有了模板類

把這些模板方法組合起來,再加上模板成員就形成了一個模板類,這些概念和行為和一般的類是一樣的。

 

template<typename T>
class Calculator
{
public:
    T m_variable;
    virtual T Add(T a, T b)
    {
        return a + b;
    };

    T Minus(T a, T b)
    {
        return a - b;
    };
};

int main()
{
    Calculator<int> c;
    cout << c.Add(2,3) << endl;
    cout << c.Minus(9,5) << endl;

    string s1 = "Hello";
    string s2 = "World";
    Calculator<string> d;
    cout << d.Add(s1,s2) << endl;
    //cout << d.Minus(s1,s2) << endl;
    return 0
} 

 

想想為什麼最後那句註釋可以編譯過,但是打開那句就編譯不過了。

我的理解,當模板類實例化的過程,如果沒有用到的方法不會被加入被實例化的模板類中,除非你顯示調用了模板類的方法。

模板類繼承

既然是類,當然不能少了繼承,模板類的繼承可以分為

直接從模板類繼承

template<typename T>
class SuperCalculator : public Calculator<T>
{
public:
    T m_variable;
    virtual T Add(T a, T b)//多態
    {
        return a + b + b;
    };

    T Multi(T a, T b)//子類
    {
        return a * b;
    };
};

 
int main()
{
    SuperCalculator<int> sc;
    cout << sc.Add(2,3) << endl;
    cout << sc.Minus(9,5) << endl;
    cout << sc.Multi(9,5) << endl;
    return 0;
};

輸出 8,4,45

從具體類繼承

class SuperIntCalculator: public Calculator<int>
{
public:
    virtual int Add(int a, int b)
    {
        return a + b + a;
    };

    int Multi(int a, int b)
    {
        return a * b;
    };
};

int main()
{
    SuperIntCalculator sc;
    cout << sc.Add(2,3) << endl;
    cout << sc.Minus(9,5) << endl;
    cout << sc.Multi(9,5) << endl;


    return 0;
};

輸出 7, 4, 45

 

模板特例化(偏特化) 

模板類可以通過繼承可以在垂直方向變化,但是類型本身也是一個水平的維度,C++為這個維度提供了變化,對於某種具體類的模板類可以擁有特殊的行為,因此我們成為特例化。

template<typename T>
class TClass
{
public:
    void PrintInfo()
    {
        printf("Hello common\n");
    };
};

template<>
class TClass<int>//特例化
{
public:
    void PrintInfo()
    {
        printf("Hello int\n");
    };
};

template<typename T>
TClass<T> * GetTClassObject(T a)
{
    return new TClass<T>;
};


int main()
{
    GetTClassObject("Hello")->PrintInfo();
    GetTClassObject(4.5)->PrintInfo();
    GetTClassObject(5)->PrintInfo();

    return 0;
};

輸出
Hello Common
Hello Common
Hello Int

如果一個模板類需要接受兩個或者兩個以上的類型來實現具體類,當其中一個類型是某個具體類的時候有特殊的行為,那麼就成為偏特化。

繼承是垂直方向上的特例化,但是特例化不是傳統面向對象體系中的概念,可以類比但不要混淆,特例化是是另外一個維度(水平),因此特例化不僅僅可以作用在類上,也能作用在模板方法上。

 

比較

>>模板和模板模式(Template Method Design Pattern)

這個設計模式也是來解決不同類型的卻有相同的處理邏輯,這個思想是一致的。但是實現卻不同,模板模式由子類去實現模板方法的每一個步驟(或者某個步驟),而且這個模式的假設是所有的類型都是來自於相同的基類,沒有解決我們最開始非固定類型。C++模板實現邏輯在類型外面(怎麼感覺又有點像策略模式,但是策略模式需要相同的介面或者基類),而類型本身可以針對不同基類的類型。其實對於模板類(方法)而言,他們雖然沒有共同的基類,但是再仔細想想,要在一個模板類中類型需要有一個抽象共性,但是這個共性不是以基類形式來表達,比如說排序,那麼輸入類型必須都要能比較大小,比如說集合,那麼輸入類型都要有“一個一個”的概念(好像不好理解,vector能處理流體問題嗎?)

>>模板和巨集

這兩個東西很容易放在一起說,比如一個簡單模板類可以通過巨集來實現沒有問題。

但是兩者是從不同角度來解決重用問題的,模板是為不同類型提供相同邏輯的重用,是站在類型的角度上看問題。巨集是為代碼級別的重用,站在少寫代碼的角度來看問題。

所以他們有重疊的部分。也提供對方不能提供的功能


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 公司準備開發一套工作流引擎,以前沒有什麼OA開發經驗,也是第一次設計工作流引擎,我把我的一些思路分享一下,希望得到些幫助或者能幫助到一些人。 產品的定位: 1、能夠做到前後端分離 2、可以做到項目的分離使用,通過介面來實現 3、支持複雜流程邏輯 例如: 填寫加班表單-》多人審核=》退回=》填寫證明人
  • 作業: 使用正則表達式和遞歸實現計算器功能。 實現: 1、實現帶括弧的計算 2、實現指數、加減乘除求餘等功能 一、實例說明: 本實例自己寫了個版本,但依舊存在一點bug,例:-2-2等計算問題,故最後在武SIR的代碼基礎上加了指數、求餘等功能。 該計算器思路: 1、遞歸尋找表達式中只含有 數字和運算
  • Python是跨平臺的語言,也即是說同樣的源代碼在不同的操作系統不需要修改就可以同樣實現 因此Python的作者就倒騰了OS模塊這麼一個玩意兒出來,有了OS模塊,我們不需要關心什麼操作系統下使用什麼模塊,OS模塊會幫你選擇正確的模塊並調用 os模塊中關於文件/目錄常用的函數使用方法os.path模塊
  • 轉載:http://blog.csdn.net/afgasdg/article/details/12757433
  • 1.主要學習這程式的編寫思路 a.讀取解釋網站 b.找到相關頁 c.找到圖片鏈接的元素 d.保存圖片到文件夾 ..... 將每一個步驟都分解出來,然後用函數去實現,代碼易讀性高. ##代碼儘快運行時會報錯,還須修改 import urllib.request import os def url_op
  • 線程問題我會分成三篇文章來給大家做個詳細的講解 一、線程的概念 1.線程是進程的組成部分,一個進程可以擁有多個線程,一個線程必須有一個父線程; 2.線程擁有自己的堆棧、自己的程式計數器和自己的局部變數,但不再擁有系統資源,它與父線程中的其他線程共用該進程所擁有的全部資源 3.線程是獨立運行的,它並不
  • 會話技術: 會話:瀏覽器訪問伺服器端,發送多次請求,接受多次響應。直到有一方斷開連接。會話結束。 解決問題:可以使用會話技術,在一次會話的多次請求之間共用數據。 分類: 客戶端會話技術 Cookie 伺服器端會話技術 Session 客戶端會話技術:Cookie 小餅干的意思 伺服器端不需要管理,方
  • 一個成熟的大型網站(如淘寶、京東等)的系統架構並不是開始設計就具備完整的高性能、高可用、安全等特性,它總是隨著用戶量的增加,業務功能的擴展逐漸演變完善的,在這個過程中,開發模式、技術架構、設計思想也發生了很大的變化,就連技術人員也從幾個人發展到一個部門甚至一條產品線。 (歡迎大家訪問我的個人網站:工
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...