在 C++ 中為了操作簡潔引入了函式模板,所謂的函式模板實際上是建立一個通用函式,其函式型別或形參型別不具體指定,用一個虛擬的型別來表達,這個通用函式就稱為函式模板,
1、通用的寫法
函式模板不是一個具體的函式,編譯器不能為其生成可執行代碼,定義函式模板后只是一個對函式功能框架的描述,當它具體執行時,將根據傳遞的實際引數決定其功能,為了容易使用,一般通用的寫法都是在頭檔案中直接定義函式模板,定義的同時也是宣告該函式,供給其它檔案包含呼叫,
1 //------fun.h或fun.hpp------// 2 #ifndef _FUN_H_ 3 #define _FUN_H_ 4 5 using namespace std; 6 7 template<typename T> 8 void fun(int b, T c, T d) //定義函式模板 9 { 10 ...... 11 } 12 13 #endif
對編譯器而言,定義函式模板的時候,編譯器并不會對它進行編譯,因為它沒有一個物體可用,編譯器只看到了宣告,只有模板被實體化后(用在特定的型別上),編譯器才會根據具體的型別對模板進行編譯,因此當在別的檔案中呼叫該函式模板時,根據傳遞的實際引數決定其功能,這樣編譯器就可以在編譯期間看到模板函式的定義并完成模板的實體化,如果在編譯的時候,找不到模板函式的定義,就先不在這一次編譯中實體化該模板函式,
2、問題的引出
但是頭檔案中定義和使用函式模板時,碰到了一個這樣的場景,即在函式模板中使用到了全域變數:
1 //------fun.h或fun.hpp------// 2 #ifndef _FUN_H_ 3 #define _FUN_H_ 4 5 using namespace std; 6 int a; //定義全域變數 7 template<typename T> 8 void fun(int b, T c, T d) //定義函式模板 9 { 10 ...... 11 a = b; 12 } 13 14 #endif
因此碰到其它多個檔案需要使用該函式模板時,都需要各自包含該函式模板的頭檔案,編譯時就會出現“全域變數重復定義”的錯誤,
嘗試按照普通函式定義和宣告分開的思路將函式模板的定義和宣告分開:
源檔案:
1 //------fun.cpp------// //錯誤做法 2 using namespace std; 3 int a; //定義全域變數 4 template<typename T> 5 void fun(int b, T c, T d) //定義函式模板 6 { 7 ...... 8 a = b; 9 }
? 頭檔案:
1 //------fun.h或fun.hpp------// //錯誤做法 2 #ifndef _FUN_H_ 3 #define _FUN_H_ 4 5 extern a; 6 template<typename T> void fun(int b, T c, T d); 7 8 #endif
? 經過嘗試,按照普通函式的方式將函式模板的定義和宣告分開,在其它檔案中呼叫函式模板,編譯時就會出現“找不到該函式定義”的錯誤,
那么有沒有辦法將函式模板的定義和宣告正確分開,提供給其它檔案包含呼叫呢,答案肯定是有的,
3、問題的解決
針對上述第2點所闡述的函式模板使用的這一場景,需要將函式模板的定義和宣告分離開來,根據實際的應用,使用以下的做法可以很好的解決這一問題,編譯和呼叫都沒有問題,
首先是源檔案*.cpp的實作:
1 //------fun.cpp------// 2 using namespace std; 3 int a; //定義全域變數 4 template<typename T> 5 void fun(int b, T c, T d) //定義函式模板 6 { 7 ...... 8 a = b; 9 } 10 11 template void fun(int b, int c, int d); //函式模板實體化,此時T被int替代 12 template void fun(int b, char c, char d); //函式模板實體化,此時T被char替代
因此在源檔案中操作有:
(1)、定義需要使用的函式模板;
(2)、在定義的函式模板后進行函式實體化操作,通過這樣的方法實作具體的模板函式,
接著是頭檔案*.h或者*.hpp的實作:
1 //------fun.h或fun.hpp------// 2 #ifndef _FUN_H_ 3 #define _FUN_H_ 4 5 extern a; 6 template<typename T> void fun(int b, T c, T d); 7 extern template void fun(int b, int c, int d); 8 extern template void fun(int b, char c, char d); 9 10 #endif
因此在頭檔案中需要的操作有:
(1)、宣告定義的函式模板;
(2)、使用extern的方式宣告實體化后的模板函式,
總結
可見,將函式模板的定義和宣告分開,需要額外在源檔案中進行函式模板的實體化再在頭檔案中進行宣告,多了一些步驟,在無特定的使用的場景中,還是建議將函式模板放在頭檔案中直接定義并呼叫;當然,如果碰到一些跨檔案呼叫的特定場景,那么采用這種將函式模板的定義和宣告分開的方法也是OK的,
更多技術內容和書籍資料獲取敬請關注微信公眾號“明解嵌入式”

本文來自博客園,作者:Sharemaker,轉載請注明原文鏈接:https://www.cnblogs.com/Sharemaker/p/17019826.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/541059.html
標籤:其他
上一篇:AI修復照片
