上一篇學習了普通函數和模板函數的區別,這一篇繼續學習兩者的調用規則。也就是在同一個文件中,如果同時存在普通函數名稱和模板函數名稱一致,那麼兩者之間的調用規則是如何。
1.如果普通函數和模板函數都可以調用,優先調用普通函數。
下面代碼,普通函數和模板函數名稱一樣,傳入參數也一致,運行代碼是調用模板函數還是普通函數
#include <iostream>
using namespace std;
//模板函數
template <class T>
void myAdd(T a, T b)
{
cout << "調用模板函數" << endl;
}
//普通函數
void myAdd(int a, int b)
{
cout << "調用普通函數" << endl;
}
void test01()
{
myAdd(10, 9);
}
int main()
{
test01();
system("pause");
return 0;
}
編譯運行
說明,如果普通函數和模板函數都可以調用,默認優先調用普通函數。
2.可以通過空模板參數列表,強制調用模板函數
如果上面的情況,我們不想默認使用普通函數,那麼就需要使用空模板函數,強制顯示調用模板函數
#include <iostream>
using namespace std;
//模板函數
template <class T>
void myAdd(T a, T b)
{
cout << "調用模板函數" << endl;
}
//普通函數
void myAdd(int a, int b)
{
cout << "調用普通函數" << endl;
}
void test01()
{
myAdd<>(10, 9);
}
int main()
{
test01();
system("pause");
return 0;
}
上面第19行使用了<>,也就是空模板參數列表。 編譯運行
3.函數模板也可以發生函數重載
我們前面學習過普通函數的重載,函數模板也可以發生重載。
#include <iostream>
using namespace std;
//模板函數
template <class T>
void myAdd(T a, T b)
{
cout << "調用模板函數1" << endl;
}
template <class T>
void myAdd(T a, T b, T c)
{
cout << "調用模板函數2" << endl;
}
//普通函數
void myAdd(int a, int b)
{
cout << "調用普通函數" << endl;
}
void test01()
{
myAdd<>(10, 9);
myAdd<>(10, 9, 1);
}
int main()
{
test01();
system("pause");
return 0;
}
上面模板函數發生重載,參數個數不一樣。
4.如果函數模板可以產生更好匹配,優先調用函數模板
有時候編譯器認爲調用普通函數和模板函數都可以,只不過普通函數可以需要隱式轉換,而模板函數如果推導出來類型,也是可以調用。這種情況下,編譯器覺得模板更好匹配,隱式轉換太麻煩,所以會優先調用函數模板
#include <iostream>
using namespace std;
//模板函數
template <class T>
void myAdd(T a, T b)
{
cout << "調用模板函數" << endl;
}
//普通函數
void myAdd(int a, int b)
{
cout << "調用普通函數" << endl;
}
void test01()
{
char a = 'a';
char b = 'b';
myAdd(a, b);
}
int main()
{
test01();
system("pause");
return 0;
}
前面學習過 char在一定範圍內是可以隱式轉換爲int類型,所以在test01()中,編譯器認爲兩個函數都可以調用,但是模板匹配更好,所以這裏有點調用了模板函數。