c/c++ 模板函數的重載


模板函數的重載

普通函數可以重載,模板函數也可以重載,但規則復雜

有下面2個函數,名字相同,返回值相同就,參數不同,符合重載。

template<typename T>
std::string moban(const T& t){}
template<typename T>
std::string moban(T* p){}

調用1

std::string s("hi");
std::cout << moban(s) << std::endl;

結果1:調用的是(const T& t),這個可以簡單理解,因為參數不是指針類型,所以不適用於(T* p)。

調用2

std::string s("hi");
std::cout << moban(&s) << std::endl;

結果2:調用的是(T* p)。這個就復雜了,因為2個模板都符合,但是調用哪個呢。

  • moban(const string*&) T被綁定到string*。
  • moban(string*) T被綁定到string。

因為(const T& t)的實例需要進行普通指針到const指針的轉換,(T* p)不需要轉換,所以是更精准的匹配。

所以推導出規則1:更精准的匹配會被優先采用。

調用3

std::string s("hi");
const std::string* sp = &s;
std::cout << moban(sp) << std::endl;

結果3:調用的是(T* p)。這個就更復雜了,因為2個模板都符合,而且都是同樣精准的匹配,但是調用哪個呢。

  • moban(const string*&) T被綁定到string*。
  • moban(string*) T被綁定到const string。

在此情況下,因為是同樣精准的匹配,所以無法區分調用哪個。但是根據重載函數模板的特殊規則,調用了(T* p)。

原因是,(const T& t)本質上可以用於任何類型,包括指針類型,比(T* p)更通用,后者只能用於指針類型。

所以推導出規則2:同樣精准的話,更特殊的會被優先采用。

如果非模板函數和模板函數同時存在,構成重載,會調用哪個?

有下面3個函數,名字相同,返回值相同就,參數不同,符合重載。

template<typename T>
std::string moban(const T& t){}
template<typename T>
std::string moban(T* p){}
std::string moban(const std::string& s){}

調用4

std::string s("hi");
std::cout << moban(s) << std::endl;

結果4:調用的是非模板的函數。

  • (const T& t) T被綁定到string,也是可以被調用的。

但是,非模板優先模板。

所以推導出規則3:非模板和模板同時都適用的時候,非模板的會被優先采用。

調用5

std::string s("hi");
std::cout << moban(s) << std::endl;

結果5:調用的是(T* p),而沒有調用非模板函數。

所以看出來,規則3有個特例,就是,如果模板的匹配比非模板的匹配更精准的時候,模板會被優先采用。

  • moban(const T& t) T被綁定到char[2]。
  • moban(T*) T被綁定到const char。
  • moban(const std::string& s) 要求從const char*到string的類型轉換。

理由:非模板也是可行的,但是需要進行一次用戶定義的類型轉換,因此她沒有模板的匹配更精准。但是2個模板都可以被調用,但是(T*)更特例化,所以最好調用的是(T*)

所以推導出規則4:非模板和模板同時都適用的時候,非模板如果需要一次用戶定義的類型轉換,而模板不需要的話,模板會被優先采用。

非模板函數和模板函數的聲明位置,導致結果的不同。

有下面4個函數,名字相同,返回值相同就,參數不同,符合重載。

template<typename T>
std::string moban(const T& t){}
template<typename T>
std::string moban(T* p){}

std::string moban(const char* p){
  return debug_rep(std::string(p));
}
std::string moban(const std::string& s){}

調用5

std::cout << moban("hello") << std::endl;

結果5:首先調用的是(const char* p),這是沒有疑問的,它是最匹配的,問題是它里面的return debug_rep(std::string(p));調用的是哪個呢?調用的是:(const T& t)。

分析:由於非模板的(const std::string& s)的定義在,(const char* p)的后面,所以return debug_rep(std::string(p));只能看到它前面的2個模板函數,所以匹配了(const T& t)。如果把(const std::string& s)的定義放在,(const char* p)的前面,return debug_rep(std::string(p));調用的就是非模板的(const std::string& s)。

c/c++ 學習互助QQ群:877684253

本人微信:xiaoshitou5854


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM