const指標與函式模板的小問題

2021-09-30 14:37:56 字數 2745 閱讀 9626

最近在寫c++pp的一道練習題時發現了一些有趣的問題,在此分享一下。

題目考察的主要是函式模板及其顯式具體化相關知識,在此為節省空間就不放出來了,以下是我最開始寫成的樣子

#include #include using namespace std;

templatet maxn (t , int);

template<> char * maxn (char * , int);

int main()

; double b[4];

char * c[5];

cout << " the biggest value in array a: " << maxn(a,6) << endl;

ios_base::fmtflags initial;

initial = cout.setf(ios_base::showpoint);

cout << " the biggest value in array b: " << maxn(b,4) << endl;

cout.setf(initial);

cout << " the biggest value in array c: " << maxn(c,5) << endl;

return 0;

}templatet maxn (t a, int lenth)

;

嗯,這樣就乙個warning也沒有了,執行一下試試

奇怪了,明明乙個錯誤也沒有,為什麼結果反倒不正確了?

在此進行debug後(此處省略過程),終於發現問題出在**了:第三次,也就是用指標陣列做引數的函式呼叫,call的是模板而非顯式具體化的形式。

也就是說編譯器沒有呼叫我們期待的char *的具體化函式,而是選擇自己進行隱式具體化乙個更加匹配的形式,呼叫了模板函式的定義。在模板定義裡:

templatet maxn (t a, int lenth)

{ t ret = a[0];

for (int i = 1;i

template<> char * maxn (char * , int);

原型宣告引數是指向非const資料的指標陣列,而實際呼叫中我們傳遞的是乙個指向const資料的指標陣列,編譯器並不能將兩者進行

精確型別匹配。再看函式模板原型:

templatet maxn (t , int);
顯然,編譯器通過匹配隱式具體化了乙個const char *的定義,而非匹配的char *的具體化。

既然如此,那我們直接顯式具體化乙個const char *的不就行了嗎?

template<> const char * maxn (const char * a, int num)

{ int flag = 0;

for(int i = 0;i

如此,編譯執行

搞定。然而,在這個過程中我又產生了乙個新的想法:如果將模板函式本身就宣告為傳遞const 陣列,這樣是否可行呢?因為在本題中我們並不需要對資料進行修改,因此新增const也是有一定必要的。說做就做

templatet maxn (const t , int);

template<> const char * maxn (const char * , int);

編譯試試

嗯?為什麼 我們的具體化原型會找不到匹配的模板呢?再仔細看看兩個的區別,原來又是引數的問題:模板函式裡宣告的是const t ,也就是不可修改的t陣列,不可修改指的是陣列的位址和指向的值都不可修改。而具體化原型裡是const char * ,也就是指向常量的指標的陣列,但是指標本身仍是變數,是可以進行修改的,想要讓指標本身也不能修改,還需要在*後加上乙個const

templateconst t maxn (const t , int);

template<> const char * const maxn (const char * const , int);

以上是修改後的原型,相應的定義裡也同樣進行修改。編譯執行,沒有錯誤。這樣就完成了修改。

以上只是模板函式及其顯式具體化與const指標的基礎知識,看起來十分簡單,但實際在基礎並不牢靠的我手裡花費了大概半天才搞清楚其中的道理,期間我也曾嘗試過使用typedef將char *替換為另乙個名字,這樣做導致的是這種const陣列確實其位址以及陣列裡的元素本身,即指標本身是不可修改的,而指標所指向的資料是可以進行修改的,但我們知道這個別名替代的是指標,在指標前面新增const也就說明指標指向的值不可修改,因此用別名宣告乙個const指標陣列在編譯器看來是沒有語法問題的,但如果試圖將指標所指向的值進行修改,程式就會崩潰;而因為typedef與預編譯指令不同不是簡單的替換,我們也不能在替換後的別名後新增const來限制。同時在本題中,也會因為編譯器認為沒有匹配的顯式具體化原型而隱式具體化乙個新的定義,導致的結果與前面所講的一樣,因此typedef的做法是不可取的。

最後還有一種簡單粗暴的方法,要什麼顯式具體化,直接過載乙個傳遞const char *的maxn函式就行了。當然,這就不再本篇的討論範圍裡了。

本篇部落格主要是記錄我在練習中犯過的一些錯誤,以示警鐘,作為乙個語言初學者,文中的錯誤及曖昧之處較多,望指正。

以上。

c 函式模板與函式指標

1 概念 與資料項相似,函式也有位址,函式的位址是儲存其機器語言 的記憶體的開始位址。獲取函式的位址很簡單 只要使用函式名 後面不跟引數 即可。也就是說,如果think 是乙個函式,則think就是該函式的位址。要將函式作為引數進行傳遞,必須傳遞函式名。c primer plus 中文版 第五版 p...

函式模板與模板函式

1.函式模板的宣告和模板函式的生成 1.1函式模板的宣告 函式模板可以用來建立乙個通用的函式,以支援多種不同的形參,避免過載函式的函式體重複設計。它的最大特點是把函式使用的資料型別作為引數。函式模板的宣告形式為 template 返回型別 函式名 參數列 其中,template是定義模板函式的關鍵字...

const與指標,const與函式

const與指標 常量指標 指向常量的指標 int b 500 1 const int a b 2 int const a b 以上中 a不允許改變,指標a可變 指標常量 指標本身是常量 3 int const a b 指標a不允許改變,a可改變 常量指標常量 4 const int const a...