C++ Template重載函數模板

    和普通函數一樣,函靈敏模板也可以被重載。就是說,相同的函數名稱可以具有不同的函數定義:於是,當使用函數名稱進行函函數調用的時候,C++編譯器必須決定究竟要調用哪個候選 函數。

//重載函數模板

#include <iostream>
#include <string>

//求兩個int值的最大值
inline int const& max(int const &a, int const& b)
{
	std::cout << "a====" << a << "   b====" << b << std::endl;
	return a < b ? b : a;
}

//求兩個任意類型值中的最大者
template <typename T>
inline T const& max(T const& a, T const& b)
{
	return a < b ? b : a;
}


//求3個任意類型值中的最大者
template<typename T>
inline T const& max(T const& a, T const& b, T const& c)
{
	return ::max(::max(a, b), c);
}



int main()
{
	std::cout << "::max(7, 42, 68)=======" << ::max(7, 42, 68) << std::endl;  //調用具有3個參數的模板
	std::cout << "::max(7.0, 42.0)=======" << ::max(7.0, 42.0) << std::endl; //調用max<double> (通過實參演繹)函數模板
	std::cout << "::max('a', 'b')========" << ::max('a', 'b') << std::endl; //調用max<char> (通過實參演繹)函數模板
	std::cout << "::max(7, 42)===========" << ::max(7, 42) << std::endl;  //調用int重載的非模板函數
	std::cout << "::max<>(7, 42)===========" << ::max<>(7, 42) << std::endl;  //調用max<int>(通過實參演繹)
	std::cout << "::max<double>(7, 42)===========" << ::max<double>(7, 42) << std::endl;  //調用max<double>(沒有實參演繹,指定T的類型爲double)
	std::cout << "::max('a', 42.7)===========" << ::max('a', 42.7) << std::endl;  //調用int重載的非模板函數
}

如例子所示,一個非模板函數可以和一個同名的函數模板同時存在,而且該函數模板還可以被實例化爲這個非模板函數。

對於非模板函數和同名的函數模板,如果其他條件都 是相同的話,那麼在調用的時候,重載解析過程通常會調用非模板函數,

而不會從該模板產生出一個函例。max(7, 42) //匹配非模板函數

    如果模板可以產生一個具有更好匹配的函數,那麼將選擇模板。這可以通過max()的第2次和第3次調用來說明:

max(7.0, 42.0); //調用max<double>(通過實參演繹)

max('a', 'b');  //調用max<char>(通過實參演繹)

還可以顯示地指定一個空的模板實參列表,這個語法好像是告訴編譯器:只有模板才能來匹配這個調用,而且所有的模板參數都應該根據調用實參演繹出來:

max<>(7, 42)  //調用max<int> (通過實參演繹)

因爲模板是不允許自動類型轉化的:但普通函數可以進行自動類型轉換,所以最後一個調用將使用非模板函數('a'和42.7都被轉化爲int):

max('a', 42.7)//對於不同類型的參數,只允許使用非模板函數

========================================================================

下面這個更有用的例子將會爲指針和普通的C字符串重載這個求最大值的模板

//重載函數模板

#include <iostream>
#include <string>
#include <cstring>


//求兩個任意類型值中的最大者
template <typename T>
inline T const& max(T const& a, T const& b) 
{
	return a < b ? b : a; 
}

//求兩個指針所指向值的最大者
template<typename T>
inline T* const& max(T* const& a, T* const &b)
{
	return *a < *b ? b : a;
}

//求兩個C字符串的最大者
inline char const* const& max(char const* const& a, char const* const& b)
{
	return std::strcmp(a, b) < 0 ? b : a;
}

int main()
{
	int a = 7;
	int b = 42;
	std::cout << "max(a, b)========" << ::max(a, b) << std::endl;//max()求兩個int值的最大值

	std::string s = "hey";
	std::string t = "you";
	std::cout << "max(s, t)========" << ::max(s, t) << std::endl;//max()求兩個std::string值的最大值

	int *p1 = &b;
	int *p2 = &a;
	std::cout << "max(p1, p2)========" << ::max(p1, p2) << std::endl;//max()求兩個指針指向值的最大者

	char const *s1 = "David";
	char const *s2 = "Nico";
	std::cout << "max(s1, s2)========" << ::max(s1, s2) << std::endl;//max()求兩個c字符串的最大值
}

    在所有重載的實現裏面,都是通過引用來傳遞每個實參的。一般而言,在重載函數模板的時候,最好只是改變那些需要改變的內容;就是說,你應該把你的改變限制在下面兩種情況:改變參數的數目或者顯示地指定模板參數。否則就可能會出現非預期的結果。例如,對於在來使用傳引用的max()模板,你用C-string類型進行重載;但對於現在(即重載版本)基於C-strings的max()函數,你是通過傳值 來傳遞參數;那麼你就不能使用3個參數的max()版本,來對3個C-string求最大值 :

//重載函數模板 字符串比較

#include <iostream>
#include <string>
#include <cstring>


//求兩個任意類型值中的最大者(通過傳引用進行調用)
template <typename T>
inline T const& max(T const& a, T const& b) 
{
	return a < b ? b : a; 
}


//求兩個C字符串的最大者(通過傳值 進地調用)
inline char const* const max(char const* a, char const* b)
{
	return std::strcmp(a, b) < 0 ? b : a;
}

//求3個任意類型值 的最大者(通過傳引用進行調用)
template<typename T>
inline T const& max(T const& a, T const& b, T const& c)
{
	return max(max(a, b), c);//注意:如果max(a, b)使用傳值調用,那麼將會發生錯誤
}

int main()
{
	std::cout << "max(7, 34, 23)========" << ::max(7, 34, 23) << std::endl;//max()求3個int值的最大值
	char const *s1 = "David";
	char const *s2 = "Nico";
	char const *s3 = "Anica";
	//錯誤:調用max(char const* a, char const* b)返回的是一個局部變量或臨時變量的地址
	//std::cout << "max(s1, s2, s3)========" << ::max(s1, s2, s3) << std::endl;
}

=============================================================

函數的所有重載版本的聲明都應該位於該函數被調用的位置之前。如果函數的定義在使用調用之後,則相同情況下不會調用之後定義的。例如:

//重載函數模板 字符串比較

#include <iostream>
#include <string>
#include <cstring>


//求兩個任意類型值中的最大者(通過傳引用進行調用)
template <typename T>
inline T const& max(T const& a, T const& b) 
{
	std::cout << "max=templates====a===" << a << "  ==== b===" << b << std::endl;
	return a < b ? b : a; 
}


//求3個任意類型值 的最大者(通過傳引用進行調用)
template<typename T>
inline T const& max(T const& a, T const& b, T const& c)
{
	return max(max(a, b), c);//使用了模板的版本,即使有下面聲明的int版本,也不會調用
}

//求兩個int值 的最大者
inline int const& max(int const& a, int const& b)
{
	std::cout << "max=====a===" << a << "  ==== b===" << b << std::endl;
	return a < b ? b : a;
}

int main()
{
	std::cout << "max(7, 34, 23)========" << ::max(7, 34, 23) << std::endl;//max()求3個int值的最大值
	return 0;
}

把max函數移到模板函數之前運行

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章