泛型
泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。
各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。将类型参数化以达到代码复用提高软件开发工作效率的一种数据类型。
函数模板
值参数化
数据的值可以通过函数参数传递,在函数定义时数据的值是未知的,只有等到函数调用时接收了实参才能确定其值。这就是值的参数化。
#include<iostream>
using namespace std;
//比较int类型大小
int myMax(int a, int b)
{
return a>b ? a : b;
}
//比较double类型大小
double myMax(double a, double b)
{
return a>b ? a : b;
}
int main()
{
//针对不同类型求最大值
cout << myMax(10, 20) << endl;
cout << myMax(1.22, 3.44) << endl;
return 0;
} 类型参数化
在C++中,数据的类型也可以通过参数来传递,在函数定义时可以不指明具体的数据类型,当发生函数调用时,编译器可以根据传入的实参自动推断数据类型。这就是类型的参数化。
template<typename T>
T max(T a, T b)
{
return a > b ? a : b;
}
max<int>(2, 3);
函数模板代表一个函数族,它所用到的数据的类型(包括返回值类型、形参类型、局部变量类型)可以不具体指定,而是用一个标识符来代替。函数调用时根据实参逆推出真正类型,生成具体函数的二进制代码。
函数模板定义
template <typename 类型参数1, typename 类型参数2, ...>
返回值类型 函数名(形参列表) {
//模板函数体
} typename可以用class替换.此处class不是表示类,因为早期C++没有typename而是用class表示类型参数名字。
函数模板的使用
函数名<参数类型1,参数类型2>(形参表);
函数名(形参表); 编译器根据调用函数模板提供的模板实参,将所调用的函数模板编译成具体函数的过程,称为函数模板的实例化。
函数模板是二次编译。编译器第一次看到函数定义,检查语法,生成内部结构。第二次,将提供的具体类型实参结合之前内部结构生成具体函数二进制指令。
函数模板隐式推断
隐式推断的同时不能做隐式类型转换
#include<iostream>
using namespace std;
//函数模板
template<typename T>
void fun(T const& a, T const& b)
{
cout << typeid(a).name() << " " << typeid(b).name() << endl;
}
template<typename T1, typename T2>
void foo(T1 const& a, T2 const& b)
{
cout << typeid(T1).name() << " " << typeid(T2).name() << endl;
}
int main()
{
fun(10, 5);
//fun(5, 10.0);//隐式推断的同时不能做隐式类型转换
foo(5, 10.0);//增加一种类型即可
cin.get();
return 0;
} 模板函数重载
重载优先选择普通版本
#include<iostream>
using namespace std;
#include<string>
//任意类型大小
template<typename T>
T const& myMax(T const& a, T const& b)
{
cout << "<TT>" << flush << endl;
return a>b ? a : b;
}
//任意指针类型大小
template<typename T>
T* const& myMax(T* const& a, T* const& b)
{
cout << "<T* T*>" << flush << endl;
return a>b ? a : b;
}
//C风格字符串的最大值
//const char* myMax(char const*a, char const*b)//加const&是为了防止拷贝构造
const char* const& myMax(char const* const& a, char const* const& b)
{
cout << "const char* const&" << endl;
return strcmp(a, b)>0 ? a : b;
}
int main()
{
const char* a = "abc";
const char* b = "def";
const char* c = "xyz";
//重载优先选择普通版本,除非函数模板能提供更好更匹配的函数
myMax(a, b);
//比较任意类型大小
myMax(10, 10);
//选择普通版本
myMax((char*)a, b);
//调用模板
myMax<>(a, b);
myMax<const char*>(a, b);
cin.get();
return 0;
}
const char* const&
<TT>
const char* const&
<T* T*>
<TT>
|