支持泛型变成的语言最适合数据结构的学习:比如C++,C++的模板技术。
C++交换变量的方法
1、宏代码块
程序实例1:宏定义实现数据的交换
#include <iostream>
using namespace std;
#define Swap(t, a, b) \
do \
{ \
t c = a; \
a = b; \
b = c; \
}while(0)
int main()
{
int a = 1;
int b = 2;
Swap(int, a, b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
double m = 3;
double n = 4;
Swap(int, m, n);
cout << "m = " << m << endl;
cout << "n = " << n << endl;
return 0;
}
2、函数,定义多个重载的函数来进行不同类型的交换
程序实例2:函数重载实现数据的交换
#include <iostream>
using namespace std;
//函数重载
void Swap(int& a, int& b)
{
int t = a;
a = b;
b = t;
}
//函数重载
void Swap(double& a, double& b)
{
double t = a;
a = b;
b = t;
}
int main()
{
int a = 1;
int b = 2;
Swap(a, b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
double m = 3;
double n = 4;
Swap(m, n);
cout << "m = " << m << endl;
cout << "n = " << n << endl;
return 0;
}
不管是宏定义,还是重载函数,进行数据交换都没那么方便,宏不安全,函数重载太麻烦,用泛型编程就不需要这么麻烦。
泛型编程的概念
不考虑具体数据类型的编程方式。
对于Swap函数可以使用泛型写法,T不是一个具体的数据类型,而是泛指任意的数据类型。
void Swap(T& a, T& b)
{
T t = a;
a = b;
b = t;
}
C++的函数模板(template)
一种特殊的函数,可以用不同类型进行调用,看起来跟普通函数很相似,区别在于类型可以被参数化。
template <typename T>
void Swap(T& a, T& b)
{
T t = a;
a = b;
b = t;
}
template关键字是告诉编译器要开始泛型编程;
<typename T>告诉编译器 T 是一个泛指类型。
函数模板的使用
1、让编译器自动推导类型并调用;
2、具体类型显式调用
程序实例3:泛型编程实现数据的交换
#include <iostream>
using namespace std;
template <typename T> //告诉编译器要进行泛型编程
void Swap(T& a, T& b)
{
T t = a;
a = b;
b = t;
}
int main()
{
int a = 0;
int b = 1;
Swap(a, b); //自动推导 T为int
cout <<"a = " << a << endl;
cout <<"b = " << b << endl;
float c = 2.5;
float d = 3.14;
Swap<float>(c, d); //显式调用,T为float
cout <<"c = " << c << endl;
cout <<"d = " << d << endl;
return 0;
}
程序实例4:泛型编程实现数据的排序
#include <iostream>
using namespace std;
//泛型编程:交换函数
template <typename T> //告诉编译器要进行泛型编程
void Swap(T& a, T& b)
{
T t = a;
a = b;
b = t;
}
//泛型编程:排序函数
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 println(T a[], int len)
{
for(int i = 0; i<len; i++)
{
cout << a[i] << ",";
}
cout << endl;
}
int main()
{
int a[5] = {5, 3, 1, 2, 4};
Sort(a, 5);
println(a,5);
string s[5] = {"Java", "C++", "C", "Python","C#"};
Sort(s, 5);
println(s,5);
return 0;
}
函数模板到底是什么
编译器从函数模板通过具体类型产生不同的函数;
编译器会对函数进行两次编译,第一次对模板代码进行编译,第二次对参数替换后的代码进行编译。
函数模板本身不是函数,它只是一个生产函数的模具,因此函数模板本身不允许隐式的类型转换,自动推导类型时,必须严格匹配;
程序实例5:
#include <iostream>
using namespace std;
template <typename T>
void Swap(T& a, T& b)
{
T t = a;
a = b;
b = t;
}
typedef void(FuncI)(int&, int&); //定义函数类型FuncI
typedef void(FuncD)(double&, double&); //定义函数类型FuncD
int main()
{
FuncI* pi = Swap; //编译器自动推导T为int
FuncD* pd = Swap; //编译器自动推导T为double
cout <<"pi = " << reinterpret_cast<void*>(pi) <<endl;
cout <<"pd = " << reinterpret_cast<void*>(pd) <<endl;
return 0;
}
输出结果:
pi = 0x402d90
pd = 0x402d40
函数模板可以定义任意多个不同的参数类型
语法:
template <typename T1, typename T2, typename T3>
对于多参数函数模板,无法自动推导出返回值的类型,可以从左向右部分指定类型参数,工程中一般将返回值的参数类型作为第一个参数类型。
//T1 = int , T2 = double, T3 = double
int r1 = Add<int>(0.5, 0.8);
//T1 = int , T2 = float, T3 = double
int r2 = Add<int, float>(0.5,0.8);
//T1 = int , T2 = float, T3 = float
int r3 = Add<int, float, float>(0.5,0.8);
程序实例6:多参数类型函数模板
#include <iostream>
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;
}
输出结果:
r1 = 1
r2 = 1.3
r3 = 1.3
函数重载遇到函数模板相遇会发生什么
函数模板可以像普通函数一样被重载:
C++编译器有限考虑普通函数,如果函数模板可以产生一个更好的匹配,就选择模板;可以通过空模板实参列表限定编译器只匹配模板
程序实例7:函数重载与函数模板
#include <iostream>
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 << "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);
}
int main()
{
int a = 1;
int b = 2;
cout << endl << Max(a, b) << endl; //优先考虑普通函数,使用int max(int a, int b)
cout << endl << Max(3.0, 4.0) << endl; //普通函数不能匹配,使用T Max(T a, T b)
cout << endl << Max(5.0, 6.0, 7.0) << endl;//普通函数不能匹配,使用T Max(T a, T b, T c)
return 0;
}
输出结果:
T Max(T a, T b)
2
T Max(T a, T b)
4
T Max(T a, T b, T c)
7
C++的类模板
以相同的方式处理不同的类型
在类声明前使用template进行标识
<typename T>用于说明类中使用了泛指类型T
类模板的使用
只能显式指出具体类型,无法自动推导,使用具体类型<Type>定义对象
#include <iostream>
using namespace std;
template <typename T>
class Op
{
public:
T process(T v)
{
return v*v;
}
};
int main()
{
Op<int> op1; //显式定义对象
Op<double> op2; //显式定义对象
cout << "5*5= " << op1.process(5) << endl;
cout << "0.3*0.3= " << op2.process(0.3) << endl;
return 0;
}