C++中的類模板

類模塊的概念和意義

在C++中有這樣一些類:

  • 主要用于存儲和組織數(shù)據(jù)元素
  • 類中數(shù)據(jù)組織的方式和數(shù)據(jù)元素的具體類型無關(guān)
  • 如:數(shù)組類,鏈表類,Stack類,Queue類等

C++中將模板的思想應(yīng)用于類,使得類的實現(xiàn)不關(guān)注數(shù)據(jù)元素的具體類型,而只關(guān)注類所需要實現(xiàn)的功能。

所以C++中的類模板是這樣的:

  • 以相同的方式處理不同類型的數(shù)據(jù)
  • 在類聲明前使用template進行標(biāo)識
  • < typename T >用于說明類中使用的泛指類型 T
  • 語法:
template<typename T>
class Operator
{
public:
    T op(T a, T b);
};

類模板的應(yīng)用:

  • 只能顯示指定具體類型,無法自動推導(dǎo)
  • 使用具體類型 < Type > 定義對象
  • 用法:
Operator <int> op1;
Operator <string> op2;
int i = op1.op(1, 2);
string s = op2.op("D.T.", "Software");

類模板的進一步理解:

  • 聲明的泛指類型 T 可以出現(xiàn)在類模板的任意地方
  • 編譯器對類模板的處理方式和函數(shù)模板相同
    • 從類模板通過具體類型產(chǎn)生不同的類
    • 在聲明的地方對類模板代碼本身進行編譯
    • 在使用的地方對參數(shù)替換后的代碼進行編譯

這里舉一個例子:

#include <iostream>
#include <string>

using namespace std;

//重載string類減號類型操作符
string operator-(string& l, string& r)
{
    return "Minus";
}

//定義一個類模板
//在類模板中有4個操作
template < typename T >
class Operator
{
public:
    T add(T a, T b)
    {
        return a + b;
    }
    T minus(T a, T b)
    {
        return a - b;
    }
    T multiply(T a, T b)
    {
        return a * b;
    }
    T divide(T a, T b)
    {
        return a / b;
    }
};

int main()
{
    //使用類模板創(chuàng)建一個對象,類型為int
    Operator<int> op1;
    //對象調(diào)用類的成員函數(shù)
    cout << op1.add(1, 2) << endl;
    
    //使用類模塊創(chuàng)建一個對象,類型為string
    Operator<string> op2;
    //對象調(diào)用類的成員函數(shù)
    cout << op2.add("D.T.", "Software") << endl;
    cout << op2.minus("D.T", "Software") << endl;
    
    return 0;
}

輸出結(jié)果為:

3
D.T.Software
Minus

類模板在工程中是怎么使用的呢?

  • 類模塊必須在頭文件中定義
  • 類模塊不能分開實現(xiàn)在不同的文件中
  • 類模塊外部定義的成員函數(shù)需要加上模板 < > 聲明

這里做一個示例:

在頭文件 Operator.h 中:

#ifndef _OPERATOR_H_
#define _OPERATOR_H_

//聲明類模塊
template < typename T >
class Operator
{
public:
    T add(T a, T b);
    T minus(T a, T b);
    T multiply(T a, T b);
    T divide(T a, T b);
};
//實現(xiàn)類模塊中各個成員函數(shù)的邏輯
template < typename T >
T Operator<T>::add(T a, T b)
{
    return a + b;
}
//實現(xiàn)類模塊中各個成員函數(shù)的邏輯
template < typename T >
T Operator<T>::minus(T a, T b)
{
    return a - b;
}
//實現(xiàn)類模塊中各個成員函數(shù)的邏輯
template < typename T >
T Operator<T>::multiply(T a, T b)
{
    return a * b;
}
//實現(xiàn)類模塊中各個成員函數(shù)的邏輯
template < typename T >
T Operator<T>::divide(T a, T b)
{
    return a / b;
}

#endif

調(diào)用使用時:

#include <iostream>
#include <string>
#include "Operator.h"

using namespace std;

int main()
{
    //使用類模塊創(chuàng)建類對象
    Operator<int> op1;
    
    //類對象使用各個成員函數(shù)
    cout << op1.add(1, 2) << endl;
    cout << op1.multiply(4, 5) << endl;
    cout << op1.minus(5, 6) << endl;
    cout << op1.divide(10, 5) << endl;
    
    return 0;
}

輸出結(jié)果為:

3
20
-1
2

多參數(shù)類模塊

在類模塊中可以定義任意多個不同的類型參數(shù),比如這樣:

template 
<typename T1, typename T2>
class Test
{
public:
    void add(T1 a, T2 b);
};

//使用
Test<int, float> t;

類模塊的特化

這里再學(xué)習(xí)一個類模塊的知識,就是它可以被 特化

  • 指定類模塊的特定實現(xiàn)
  • 部分類型參數(shù)必須顯示指定
  • 根據(jù)類型參數(shù)分開實現(xiàn)類模塊
  • 語法:
template
<typename T1, typename T2>
class Test
{
};

//特化
template
<typename T>
class Test <T, T>
{
};

類模塊可以被 特化 ,當(dāng)然對于特化還有特化類型:

  • 部分特化 --- 用特定規(guī)則約束類型參數(shù)
  • 完全特化 --- 完全顯示指定類型參數(shù)
template
<typename T1, typename T2>
class Test
{
};

//完全特化
template
<  >
class Test < int, int >
{
};

這里舉一個例子:

#include <iostream>
#include <string>

using namespace std;

template
< typename T1, typename T2 >
//正常的類模塊
class Test
{
public:
    void add(T1 a, T2 b)
    {
        cout << "void add(T1 a, T2 b)" << endl;
        cout << a + b << endl;
    }
};

template
< typename T1, typename T2 >
// 關(guān)于指針的特化實現(xiàn)
//部分特化:用指針類型約束類型參數(shù)
class Test < T1*, T2* >
{
public:
    void add(T1* a, T2* b)
    {
        cout << "void add(T1* a, T2* b)" << endl;
        cout << *a + *b << endl;
    }
};

template
< typename T >
// 當(dāng) Test 類模板的兩個類型參數(shù)完全相同時,使用這個實現(xiàn)
//部分特化:用參數(shù)類型完全相等的規(guī)則約束
class Test < T, T >
{
public:
    void add(T a, T b)
    {
        cout << "void add(T a, T b)" << endl;
        cout << a + b << endl;
    }
    void print()
    {
        cout << "class Test < T, T >" << endl;
    }
};

template
<  >
// 當(dāng) T1 == void* 并且 T2 == void* 時
//完全特化 完全顯示指定類型參數(shù)
class Test < void*, void* >
{
public:
    void add(void* a, void* b)
    {
        cout << "void add(void* a, void* b)" << endl;
        cout << "Error to add void* param..." << endl;
    }
};

int main()
{  
    //2個類型不同,調(diào)用普通類模塊
    Test<int, float> t1;
    //2個類型相同,調(diào)用用參數(shù)類型完全相等的規(guī)則約束的類模塊
    Test<long, long> t2;
    //2個類型完全相等,并且符合已經(jīng)指定參數(shù)類型的類模板
    Test<void*, void*> t3;
    
    t1.add(1, 2.5);
    
    t2.add(5, 5);
    t2.print();
    
    t3.add(NULL, NULL);
    //2個參數(shù)都為指針,且類型不同
    //調(diào)用用指針類型約束類型參數(shù)的類模板
    Test<int*, double*> t4;
    int a = 1;
    double b = 0.1;
    
    t4.add(&a, &b);
    
    return 0;
}

輸出結(jié)果為:

void add(T1 a, T2 b)
3.5
void add(T a, T b)
10
class Test < T, T >
void add(void* a, void* b)
Error to add void* param...
void add(T1* a, T2* b)
1.1

使用類模塊特化也要注意一些地方:

  • 特化只是模塊的分開實現(xiàn)
    • 本質(zhì)上是同一個類模塊
  • 特化類模板的使用方式是統(tǒng)一的
    • 必須顯示指定每一個類型參數(shù)

類模塊特化的進一步理解

其實有沒有發(fā)現(xiàn)特化和重定義有點相似,但也有些區(qū)別:

  • 重定義
    • 一個類模塊和一個新類(或者兩個類模塊)
    • 使用的時候需要考慮如何選擇的問題
  • 特化
    • 以統(tǒng)一的方式使用類模塊和特化類
    • 編譯器自動優(yōu)先選擇特化類

那既然類模塊可以特化,函數(shù)模塊可不可以特化呢?

  • 函數(shù)模板只支持類型參數(shù)完全特化
  • 使用方法:
template
<typename T>
//函數(shù)模塊定義
bool Equal(T a, T b)
{
    return a == b;
}

template
< >
//函數(shù)模塊完全特化
bool Equal<void *>(void* a, void* b)
{
    return a == b;
}

這里舉一個例子:

#include <iostream>
#include <string>

using namespace std;

//普通函數(shù)模塊
template
< typename T >
bool Equal(T a, T b)
{
    cout << "bool Equal(T a, T b)" << endl;
    
    return a == b;
}

//完全特化后的函數(shù)模塊
template
< >
bool Equal<double>(double a, double b)
{
    const double delta = 0.00000000000001;
    double r = a - b;
    
    cout << "bool Equal<double>(double a, double b)" << endl;
    
    return (-delta < r) && (r < delta);
}

//普通函數(shù)
bool Equal(double a, double b)
{
    const double delta = 0.00000000000001;
    double r = a - b;
    
    cout << "bool Equal(double a, double b)" << endl;
    
    return (-delta < r) && (r < delta);
}

int main()
{  
    //調(diào)用函數(shù)
    cout << Equal( 1, 1 ) << endl;
    //調(diào)用完全特化后的函數(shù)模塊
    cout << Equal<>( 0.001, 0.001 ) << endl;
    
    return 0;
}

輸出結(jié)果為:

bool Equal(T a, T b)
1
bool Equal<double>(double a, double b)
1

這里要注意:

當(dāng)需要重載函數(shù)模塊時,優(yōu)先考慮使用模板特化;當(dāng)模板特化無法滿足需求,再使用函數(shù)重載!

小結(jié)

  • 泛型編程的思想應(yīng)用于類的形式就是類模塊
  • 類模板以相同的方式處理不同類型的數(shù)據(jù)
  • 類模塊非常適用于編寫數(shù)據(jù)結(jié)構(gòu)相關(guān)的代碼
  • 類模塊在使用時只能顯示指定類型
  • 類模塊可以定義任意多個不同的類型參數(shù)
  • 類模塊可以被部分特化和完全特化
  • 特化的本質(zhì)是模板的分開實現(xiàn)
  • 函數(shù)模板只支持完全特化
  • 工程中使用模板特化代替類(函數(shù))重定義
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,694評論 19 139
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,691評論 1 51
  • C++ 模板簡介 一、模板 使用模板的目的就是能夠讓程序員編寫與類型無關(guān)的代碼。 模板是一種對類型進行參數(shù)化的工具...
    MinoyJet閱讀 2,540評論 0 12
  • 俗話說:人在職場混,哪能不挨刀。 職場潛規(guī)則猶如宮斗般精彩,誰都可能中槍,誰都可能背后插你一刀。 遇到愛給你穿小鞋...
    msdone閱讀 486評論 0 0
  • 我的夢想:成為一名優(yōu)秀的幼師! 1職業(yè)目標(biāo):在畢業(yè)后進入早教行業(yè)top10的天才寶貝早教公司實習(xí),并爭取拿下該公...
    稚童千陽閱讀 445評論 0 0

友情鏈接更多精彩內(nèi)容