对于这种 1.函数的业务逻辑一样 2.函数的参数类型不一样 的多次重复型函数,为了节省开发工作,提出泛型编程
泛型编程:即用template定义一个泛型T,用它来统代类型
全文内容包括以下几点:
1.泛型函数的基础
2.函数模板的强化(数组的泛型应用)
3.函数模板与函数重载
4.函数模板云函数重载相遇时的调用规则
1.泛型函数的基础
1.1函数模板分为显示调用和隐式调用,即主动地声明模板函数接收参数类型和传入参数时模板自动匹配,推荐显示调用
#include "iostream"
using namespace std;
void change01(int &a, int &b)//普通函数
{
int c;
c = a;
a = b;
b = c;
}
void change02(char &a, char &b)
{
char c;
c = a;
a = b;
b = c;
}
template <typename T>//函数模板的定义
void change03(T &a, T &b)
{
T c;
c = a;
a = b;
b = c;
}
void main01()
{
{
//int 类型的调用,现在要求交换char类型(必须重写change函数)
int a = 10;
int b = 20;
change01(a, b);
cout << "a=" << a << " b=" << b << endl;
}
{
char x = 'x';
char y = 'y';
change02(x, y);
printf("a=%c b=%c\n", x, y);
cout << "x=" << x << " y=" << y << endl;
}
}
//函数模板的调用
// 显示类型 调用
// 自动类型 推导
void main02()
{
{
int a = 10;
int b = 20;
change03<int>(a, b);//1. 显示类型 调用 (就是函数后面,参数列表前面用<>显示参数类型)
cout << "a=" << a << " b=" << b << endl;
change03(a, b);//2. 自动类型 推导
cout << "a=" << a << " b=" << b << endl;
}
{
char x = 'x';
char y = 'y';
change03<char>(x, y);//1. 显示类型 调用
cout << "x=" << x << " y=" << y << endl;
change03(x, y);//2. 自动类型 推导
cout << "x=" << x << " y=" << y << endl;
}
}
2.函数模板的强化(数组的泛型应用)
2.1可以同时定义两个函数模板,使用时必须声明两个模板的类型
#include "iostream"
using namespace std;
template <typename T>
void mysort(T array[],T size)
{
for (int i = 0; i < size; i++)
{
for (int j = i + 1; j < size; j++)
{
if (array[i] < array[j])
{
T tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
}
}
}
template <typename T,typename T2>//可以同时定义两个函数模板
void print(T array[],T2 size)
{
for (int i = 0; i < size; i++)
{
cout << array[i] << ",";
}
cout << endl;
}
void main03()
{
// int类型
{
int array[] = { 132,132,456,4,68465,464,6546,435,4864,4,864,6546,4 };
int size = sizeof(array) / sizeof(array[0]);
mysort<int>(array, size);
print<int, int>(array, size);
}
//char 类型
char buf[] = "qwertyuiopasfhadbvebv16469846";
int size = sizeof(buf) / sizeof(char);
mysort<char>(buf, size);//这样是不规范的,这样会将size转换成char类型
print<char, int>(buf, size);
}
3.函数模板与函数重载
3.1普通函数可以进行隐式的参数转换,但是函数模板必须严格的匹配不会进行自动类型转换
#include "iostream"
using namespace std;
template <typename T>
void myswap(T &a, T &b)
{
T c = 0;
c = a;
a = b;
b = c;
cout << "我是模板函数" << endl;
}
void myswap(int a, char c)//函数重载
{
cout << "a:" << a << "c:" << c ;
cout << "我是普通函数" << endl;
}
void main04()
{
int a = 10;
char c = 'z';
myswap(a, c); // 普通函数的调用
myswap(c, a); //普通函数的调用: 可以进行隐式的类型转换
myswap<int>(a, a); // 函数模板函数的调用(本质:类型参数化): 将严格的按照类型进行匹配,不会进行自动类型转换.
}
4.函数模板云函数重载相遇时的调用规则
4.1 函数模板可以像普通函数一样被重载
4.2 C++编译器优先考虑普通函数
4.3 如果函数模板可以产生一个更好的匹配,那么选择模板
4.4 可以通过空模板实参列表的语法限定编译器只通过模板匹配
#include "iostream"
using namespace std;
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)
{
cout << "T Max(T a, T 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);
}
void main05()
{
int a = 1;
int b = 2;
cout << Max(a, b) << endl; //当函数模板和普通函数都符合调用时,优先选择普通函数
cout << Max<>(a, b) << endl; //若强制使用函数模板,则显示使用空 <> 类型列表
cout << Max(3.0, 4.0) << endl; //如果 函数模板产生更好的匹配 使用函数模板
//在普通函数的形参列表为int类型,但是传递的实参是double型,为避免参数失真,选择模板函数匹配
cout << Max(5.0, 6.0, 7.0) << endl; //重载
cout << Max('a', 100) << endl; //调用普通函数 可以隐式类型转换
system("pause");
return;
}