1. 函数模板深入理解
(1)编译器从函数模板通过具体类型产生不同的函数
(2)编译器会对函数模板进行两次编译
①对模板代码本身进行编译
②对参数替换后的代码进行编译(编译时机:可能发生在定义对象或函数调用时)
(3)注意事项
①函数模板本身不允许隐式类型转换
②自动推导类型时,必须严格匹配
③显式类型指定时,能够进行隐式类型转换
【编程实验】函数模板的本质
#include <iostream> #include <string> using namespace std; class Test { Test(const Test&){} public: Test() { } }; template <typename T> void Swap(T& a, T& b) { T c = a; a = b; b = c; } typedef void (FuncI)(int&, int&); typedef void (FuncD)(double&, double&); typedef void (FuncT)(Test&, Test&); int main() { FuncI* pi = Swap; //编译器自动推导T为int //当编译到这行时,发生要用一个模板去初始化pi //而pi的类型又是void (FuncI)(int&, int&),所以 //此时,编译器会用int去替换T,然后生成一个Swap函数 //并把指针赋值给pi FuncD* pd = Swap;//编译器自动推导T为double,编译器生成另一个Swap函数 //以下证明pi与pd指向的是两个不同的函数 cout << "pi = " << reinterpret_cast<void*>(pi) << endl; //0x40283c cout << "pd = " << reinterpret_cast<void*>(pd) << endl; //0x402818 //FuncT* pt = Swap; //编译器自动推导T为test。但是当进行T替换时 //由于Swap函数内部的T c = a;会调用Test的拷贝 //构造函数,但被我们故意设为private,所以编译 //出错,这个例子是用来说明会生成另一个不同的 //版本的Swap函数。 //cout << "pt = " << reinterpret_cast<void*>(pt) << endl; return 0; }
2. 多参数函数模板
(1)可定义任意多个不同的类型参数,如
template <typename T1, typename T2, typename T3>
T1 Add(T2 a, T3 b)…
…
int r = Add<int, float, double>(0.5, 0.8);//函数调用
(2)对于多参数函数模板
①无法自动推导返回值类型
②可以从左向右部分指定类型参数
③工程中将返回值参数作为第一个类型参数!
【编程实验】多参数函数模板
#include <iostream> #include <string> using namespace std; template <typename T1, typename T2, typename T3> T1 Add(T2 a, T3 b) { return static_cast<T1>(a + b); } int main() { //T1 = int, T2 = double, T3 = double int r1 = Add<int>(0.5, 0.8); //从左向右指定类型,这里只指定返回值,其余自动推导 //T1 = double, T2 = float, T3 = double double r2 = Add<double, float>(0.5, 0.8); //从左向右指定类型,这里只指定返回值和 //add函数的第1个参数,第2个参数自动推导 //T1 = float, T2 = float, T3 = float float r3 = Add<float, float, float>(0.5, 0.8); //3个类型都显式指定 cout << "r1 = " << r1 << endl; //r1 = 1 cout << "r2 = " << r2 << endl; //r3 = 1.3 cout << "r3 = " << r3 << endl; //r3 = 1.3 return 0; }
3. 函数重载遇见函数模板会发生什么?
(1)C++编译器优先考虑普通函数
(2)如果函数模板可以产生一个更好的匹配,那么选择模板
(3)可以通过空模板实参列表限定编译器只匹配模板
int r1 =Max(1, 2);
int r2 = Max<>(0.5, 0.8); //<>表示只能去从模板中匹配
【实例分析】重载函数模板
#include <iostream> #include <string> using namespace std; template <typename T> T Max(T a, T b) { cout << "T Max(T a, T b)" << endl; return a > b ? a : b; } int Max(int a, int b) { cout << "int Max(int a, int b)" << endl; return a > b ? a : b; } template <typename T> T Max(T a, T b, T c) { cout << "T Max(T a, T b, T c)" << endl; return Max(Max(a, b), c); } int main() { int a = 1; int b = 2; cout << Max(a, b) << endl; //优先匹配普通函数: int Max(int a, int b) cout << Max<>(a, b) << endl; //限定只能从函数模板去匹配:int Max<int>(int,int) cout << Max(3.0, 4.0) << endl; //不匹配普通函数,从函数模板中匹配Max<double>(double, double) cout << Max(5.0, 6.0, 7.0) << endl;//函数模板 Max<double>(double, double, double) cout << Max(‘a‘, 100) << endl; //普通成员函数int Max(int a, int b)。由于函数模板(只有一个参数类型T) //本身不允许隐式转换,所以不会匹配函数模板。 return 0; } /* int Max(int a, int b) 2 T Max(T a, T b) 2 T Max(T a, T b) 4 T Max(T a, T b, T c) T Max(T a, T b) T Max(T a, T b) 7 int Max(int a, int b) 100 */
4. 小结
(1)函数模板通过具体类型产生不同的函数
(2)函数模板可以定义任意多个不同的类型参数
(3)函数模板中的返回值类型必须显式指定
(4)函数模板可以像普通函数一样被重载
时间: 2024-10-04 04:29:05