1. 程式人生 > >C++模板之函式模板

C++模板之函式模板

泛型程式設計

編寫與型別無關的邏輯程式碼,是程式碼複用的一種手段。模板是泛型程式設計的基礎

模板

代表一個函式家族,該函式與型別無關,在使用時被引數化,根據實參型別產生函式的特定型別版本(它本身不是類或函式)

模板函式的格式

這裡寫圖片描述

模板的例項化

產生模板特定型別的過程稱為函式模板的例項化

template <typename T>
T Add(T left,T right)
{
    return left + right;
}
int main()
{
    Add(1,2);
    Add(1.0,2.0);
    Add('1'
,'1'); Add(1,1.0);//error:模板引數“T”不明確 //模板函式不會進行型別轉換 Add<int>(1, '1');//顯式例項化 Add<double>(1, 1.0); Add(1,(int) 1.0);//隱式例項化 return 0; }
模板的實參推演

從函式實參確定模板形參型別和值得過程稱為模板實參推斷

型別形參轉換

一般不會轉換實參已匹配以有的例項化,相反會產生新的例項;
編譯器只會執行兩種轉換:1.const轉換;2.陣列或函式到指標的轉換

  • const轉換

    接收const引用或const指標的函式可以分別用非const物件的引用或者指標來呼叫

  • 陣列或函式到指標的轉換

    如果模板形參不是引用型別,則對陣列或函式型別的實參應用常規指標轉換。陣列實參將當做指向其第一個元素的指標,函式實參當做指向函式型別的指標

模板形參
  • 模板型別引數
typedef double T;
//模板形參的名字在同一模板中只能使用一次
template <typename T, typename T>// error C2991: 重定義 模板 引數“T”
//所有模板形參前必須加上class/typename關鍵字修飾
template <typename T,U>//error C2061: 語法錯誤: 識別符號“U”
template
<typename T = int> //可以指定預設的模板實參 T Add(T left=1, T right=2 )//預設的呼叫引數 { cout << "T type = " << typeid(T).name() << endl;//列印模板引數T的型別 return left + right; } T val;//全域性變數 int main() { Add(); cout << "T type = " << typeid(T).name() << endl;//列印全域性變數的型別 return 0; }

這裡寫圖片描述

模板形參的名字只能在模板形參之後到模板宣告或定義的末尾使用

  • 非模板型別引數
    模板內部定義的常量
template <typename T = int ,int N = 10>  //N:非模板型別引數
void Funtest(T(&_array)[N])   //陣列引用
{
    for (int i = 0; i < N; ++i)
    {
        _array[i] = 0;
    }
}
int main()
{
    const int c = 3;
    int a[4];
    int b[c + 1];  
    Funtest(a);
    Funtest(b);
    return 0;
}
模板函式和同名非模板函式
int Max(const int& a, const int& b)   //同名的非模板函式和模板函式可以同時存在
{
    return a > b ? a : b;
}
template <typename T>
T Max(const T& a,const T& b)
{
    return a > b ? a : b;
}
template <typename T1, typename T2>
T1 Max(const T1& a, const T2& b)
{
    return a > b ? a : b;
}
int main()
{
    Max(1, 2);//優先呼叫非模板函式
    Max<>(1, 2);//顯示指定,只能呼叫模板
    Max(1, 2.0);//優先呼叫優化模板template <typename T1, typename T2>
    return 0;
}
模板特化
  • 特化格式
    這裡寫圖片描述
template <typename T>//模板例項
int compare(T a,  T b)//比較了地址
{
    if (a < b)
        return -1;
    if (a>b)
        return 1;
    return 0;
}
template <>//模板特化    在模板例項之後
//特化的宣告必須與特定的模板相匹配
//int compare<const char*>(char* p1, char*  p2)//error :不是函式模板的專用化
int compare<const char*>(const char* p1, const char*  p2)
{
    return strcmp(p1,p1);
}
int main()
{
    char* p1 = "abcd";
    char* p2 = "abce";
    const char* p3 = "abcd";
    const char* p4 = "abce";
    cout << compare(p1, p2) << endl;
    cout << compare(p3, p4) << endl;
    return 0;
}
模板過載
template <typename T>
T Max(const T& a, const T& b)
{
    return a > b ? a : b;
}
template <typename T>
T Max(const T& a, const T& b, const T& c)//過載
{
    return Max(Max(a, b), c);
}
int main()
{
    Max(1, 2);
    Max(1, 2, 4);
    return 0;
}