对于函数体相同,仅仅参数类型不同的函数我们可以使用函数模板来解决,这是 C++ 中的一种泛型编程。
编程实验:模板函数初探
// 42-1.cpp
#include
#include
using namespace std;
template<typename T>
void Swap(T& a, T& b)
{
T c = a;
a = b;
b = c;
}
template<typename T>
void Sort(T a[], int len)
{
for (int i = 0; i < len; i++)
{
for (int j = i; j < len; j++)
{
if (a[i] > a[j])
{
Swap(a[i], a[j]);
}
}
}
}
template<typename T>
void print(T a[], int len)
{
for (int i = 0; i < len; i++)
{
cout << a[i] << ", ";
}
cout << endl;
}
int main()
{
int a[5] = {4, 5, 1, 3, 2};
Sort(a, 5);
print(a, 5);
string s[5] = {"Java", "C++", "Go", "Python", "C"};
Sort(s, 5);
print(s, 5);
return 0;
}
$ g++ 42-1.cpp -o 42-1
$ ./42-1
1, 2, 3, 4, 5,
C, C++, Go, Java, Python,
编译器对函数模板进行两次编译
注意事项:函数模板本身不允许隐式类型转换
编程实验:函数模板的本质
// 42-2.cpp
#include
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定义函数类型
typedef void(FuncI)(int&, int&);
typedef void(FuncD)(double&, double&);
typedef void(FuncT)(Test&, Test&);
int main()
{
FuncI* pi = Swap;
FuncD* pd = Swap;
//FuncT* pt = Swap;
cout << "pi = " << reinterpret_cast<void*>(pi) << endl;
cout << "pd = " << reinterpret_cast<void*>(pd) << endl;
//cout << "pt = " << reinterpret_cast(pt) << endl;
return 0;
}
编译运行
$ g++ 42-2.cpp -o 42-2
$ ./42-2
pi = 0x55daa8490a01
pd = 0x55daa8490a2e
可以看到函数指针的地址不同。
编程实验:多参数函数模板
// 42-3.cpp
#include
using namespace std;
template<typename T1, typename T2, typename T3>
T1 add(T2 a, T3 b)
{
return static_cast<T1>(a + b);
}
int main()
{
int r1 = add<int>(0.5, 0.8);
double r2 = add<double, float>(0.5, 0.8);
float r3 = add<float, float, float>(0.5, 0.8);
cout << "r1 = " << r1 << endl;
cout << "r2 = " << r2 << endl;
cout << "r3 = " << r3 << endl;
return 0;
}
$ g++ 42-3.cpp -o 42-3
$ ./42-3
r1 = 1
r2 = 1.3
r3 = 1.3
函数模板可以像普通函数一样重载
// 42-3.cpp
#include
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 << endl; // 普通函数 MAX(int, int)
cout << MAX<>(a, b) << endl << endl; // 函数模板 MAX(int, int)
cout << MAX(3.0, 4.0) << endl << endl; // 函数模板 MAX(double, double)
cout << MAX(5.0, 6.0, 7.0) << endl << endl; // 函数模板 MAX(double, double, double)
cout << MAX('a', 70) << endl << endl; // 普通函数 MAX(int, int)
return 0;
}
优先考虑普通函数;如果函数模板有更好的匹配,则选择模板;也可以通过空模板实参列表只匹配模板
编译运行
$ g++ 42-4.cpp -o 42-4
$ ./42-4
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)
97
1、函数模板能够根据实参对参数类型进行推导
2、可以自动类型推导调用,也可以显示指定参数类型
3、函数模板通过具体类型产生不同的函数
4、寒素模板可以定义多个不同的类型参数
5、函数模板可以重载