国产亚洲精品久久久一区,国产丰满老熟女重口对白 ,国产乱子伦农村xxxx,国产精品vⅰdeoxxxx国产,国产精品久久久久久人妻无

網(wǎng)站首頁 綜合導(dǎo)航 全能搜索 網(wǎng)站地圖 聯(lián)系我們

首頁 > 教程 > 模板知識

模板基礎(chǔ)知識之函數(shù)模板

  • 分類 : 模板知識
  • 編輯 : 大寶123
  • 發(fā)布 : 10-27
  • 閱讀 :745

一、簡介

該篇主要內(nèi)容為介紹函數(shù)模板以及函數(shù)模板的基本用法。

二、編程環(huán)境

系統(tǒng):Windows11
IDE:Visual Studio2022
項目名字:funcTemp

三、內(nèi)容

1.基本范例

1.1函數(shù)模板的作用

舉例說明:編程過程中,數(shù)據(jù)類型千奇百怪,僅表示數(shù)字的常見的就有int,float,double等多種類型。這些數(shù)字在數(shù)學(xué)中,都可以進(jìn)行相加,相減,相乘,相除,多次方運算等等多種運算模式。但是在計算機中,并不能一概而論,每種不同的數(shù)據(jù)類型,計算機都很較真的做了區(qū)分,int和int進(jìn)行計算,double和double進(jìn)行計算。拿減法來說,就會產(chǎn)生以下的代碼。

int Sub(int a, int b)
{
    return a - b;
}
double Sub(double a, double b)
{
    return a - b;
}

如上面代碼所示,一個減法,卻要寫出兩個函數(shù),如果是更復(fù)雜的運算,函數(shù)內(nèi)容更多,幾十行甚至上百行代碼,達(dá)成同一個目的,僅僅因為類型不同,就需要重寫一遍函數(shù),就會造成代碼冗余,不好看,使得工程變得非常龐大。為了解決這個問題所以我們需要模板。

1.2函數(shù)模板的舉例

接著上面的例子,減法運算,我們可以用一個函數(shù)解決

template <typename T>
T Sub(T a, T b)
{
    return a - b;
}

調(diào)用時,類型T會被編譯器自動的,識別為所給參數(shù)的類型。
調(diào)用舉例

int y = Sub(5, 3);

調(diào)用驗證,使用VS自帶的工具,搜索Developer Command Prompt for vs2022,打開后進(jìn)入命令行,進(jìn)入到工程編譯的文件夾路徑下。會生成一個funcTemp.obj的文件。使用dumpbin命令來驗證調(diào)用過程中,編譯器自動識別類型T的正確性。

dumpbin /all funcTemp.obj > funcTemp.txt

就會在該文件夾下生成一個funcTemp.txt文件。查看funcTemp.txt文件。搜索函數(shù)名,就可以看到,sub()函數(shù),自動的把T類型識別為了int類型

COMDAT; sym= "int __cdecl Sub<int>(int,int)" (??$Sub@H@@YAHHH@Z)

1.3函數(shù)模板說明

1.template :表示函數(shù)模板的開始,是C++中的關(guān)鍵字
2.typename:typename修飾的是類型T,語法規(guī)定的寫法。也可以用class代替,不過我的習(xí)慣是函數(shù)模板中用typename,在類模板中用class。
3.T:T表示一個類型,可以是任意的,也可以是X,Y,L等等
4.函數(shù)體中,與普通函數(shù)類似,只需要主要如果是T類型的,就一定寫T就好。

template <typename T>                       
T Sub(T a, T b)
{
    return a - b;
}

1.4多個類型的函數(shù)模板使用

上面介紹的內(nèi)容中,T要么是指代了int要么是指代了double,如果是int-double呢,或者int+double+int呢。所以函數(shù)模板也可以“傳入多個T類型”。簡單的例子如下。

template <typename T,typename U,typename K>                       
T Sub(T a, U b, K c)
{
    return a - b - c;
}

2.模板函數(shù)的重載

普通函數(shù)可以重載,只要參數(shù)數(shù)量不同,參數(shù)類型不同,即可完成重載。與函數(shù)重載非常類似。下面用代碼說明。

template<typename T>
void myFunc(T a)
{
    std::cout << "myFunc(T a) is done" << std::endl;
}

template<typename T>
void myFunc(T* a)
{
    std::cout << "myFunc(T* a) is done" << std::endl;
}

上面模板函數(shù)完成了重載,第一個傳入的是T類型的參數(shù),第二個傳入的是T*類型參數(shù)。參數(shù)類型不同,就是一個重載的(模板)函數(shù)。

3.特化

3.1.全特化

模板函數(shù)屬于是泛化,具有不確定性,廣泛性的模式,與之相反的,全特化,就是確定的,指定的模式。
寫一個模板函數(shù)

template<typename T,typename U>
void myFunc(T* a , U& b)
{
    std::cout << "myFunc(T* a , U& b) is done" << std::endl;
}

這里的T與U都是不確定的,在調(diào)用的時候,編譯器自動編譯確定類型。
下面寫一個全特化版本

template<>
void myFunc(char* a , int& b)
{
    std::cout << "myFunc(char* a , int& b) is done" << std::endl;
}

這里注意看,<>里面是空的!,函數(shù)體里確定了,第一個參數(shù)是char*類型,第二個參數(shù)是int& 類型。但是要知道的是,看起來挺像重載,但記住,全特化不等于重載。全特化只是實例化了一個函數(shù)模板。

3.2.偏特化

在模板函數(shù)中,偏特化并不方便實現(xiàn),只能通過重載的方式來實現(xiàn),但是很少會在實際開發(fā)中使用到,這里不過多說明(真的用不到,類里面才會比較方便使用)。

四、注意點

1.不要讓模板函數(shù)有不確定的類型

注意看以下代碼。

template <typename T,typename U,typename V>
V Add(T a, U b)
{
    return a + b;
}
int main()
{
    std::cout << Add(2 , 3.5) << std::endl;
    return 0;
}

編譯時會報錯,原因是返回類型V并不能被編譯器推斷出來。改進(jìn)的方法有兩種,我比較傾向于第二種。
方法一:指定返回值類型,并且將返回值類型放到第一位,注意對比上面的代碼,V被放到了第一位,調(diào)用的時候也顯式的指出了V的類型。

template <typename V,typename T,typename U>
V Add(T a, U b)
{
    return a + b;
}
int main()
{
    std::cout << Add<double>(2 , 3.5) << std::endl;
    return 0;
}

方法二:使用auto關(guān)鍵字。這樣返回值類型就不用管傳入的類型,讓編譯器自己去推斷。會更加方便,我比較傾向于這種方式。

template <typename T,typename U>
auto Add(T a, U b)
{
    return a + b;
}
int main()
{
    std::cout << Add(2 , 3.5) << std::endl;
    return 0;
}

2.使用隱式轉(zhuǎn)換,改變傳入的參數(shù)

在一些開發(fā)過程中,傳入的參數(shù)可能不是我們想要的參數(shù),總會多一些煩人的小數(shù)點,我們可以用隱式轉(zhuǎn)換,改變傳入的參數(shù)類型,下面函數(shù),傳入的類型為double類型,我們不想要2.3,我們只要2,就必須顯式的指出傳入類型。

template < typename U>
auto MySquare(U a)
{
    return a * a;
}
int main()
{
    std::cout << MySquare(2.3) << std::endl;
    std::cout << MySquare<int>(2.3) << std::endl;
    return 0;
}

3.函數(shù)調(diào)用的優(yōu)先級

一個程序中,可以有函數(shù)模板,可以特化,可以有功能相同的普通函數(shù),那么編譯器會優(yōu)先調(diào)用哪一個類型的函數(shù)呢?

//模板函數(shù)
template <typename T>
void Temp(T a)
{
     std::cout << "temp  is run" << std::endl;
}
//全特化
template <>
void Temp(int a)
{
     std::cout << "spacial temp is run" << std::endl;
}
//功能相同的普通函數(shù)
void Temp(int a)
{
     std::cout << "general func  is run" << std::endl;
}

int main()
{
    Temp(8);
    return 0;
}

看結(jié)果,是普通函數(shù)被調(diào)用了,我們把普通函數(shù)屏蔽了之后,是特化的模板函數(shù)被調(diào)用了。所以可以得出結(jié)論,函數(shù)調(diào)用的順序是普通函數(shù) > 特化的模板函數(shù) > 泛化的模板函數(shù)

五、總結(jié)

模板函數(shù)的基礎(chǔ)使用方法,基本上就這么多了,如果有錯誤歡迎指正。這是一些看王建偉老師編寫的《C++新經(jīng)典 模板與泛型編程》*一書過程中的理解。歡迎交流。



作者:唐予清
鏈接:https://www.jianshu.com/p/6335ed2ff0a4
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。