C++内存管理5-标准分配器之基础函数模板类模板
- 先介绍下泛型编程
顾名思义,泛型编程就是支持多种类型的通用代码,说多种其实不严谨,应该是与类型无关的通用代码。目的是为了提高代码的复用率。
2.函数模板:
先骑自行车:
template<typename T>
void swapTy(T &a,T &b)
{
T temp = a;
a = b;
b = temp;
}
void main()
{
int a = 20;
int b = 30;
cout << "source:" << "a:" << a << " b:" <<b<< endl;
//第一种调用方法
swapTy<int>(a, b);
cout << "changed:" << "a:" << a << " b:" << b << endl;
double a1 = 20.99;
double b1 = 30.222;
cout << "source:" << "a1:" << a1 << " b1:" << b1 << endl;
//第二种调用方法
swapTy(a1, b1);
cout << "changed:" << "a1:" << a1 << " b1:" << b1 << endl;
system("pause");
}
结果:
函数模板代表了一个函数家族,该函数模板和类型无关,在使用的时候才被参数化,编译器会根据用户传入的参数去自动推演生成相应的函数。
函数模板还可以定义任意多个不同的类型参数,但是对于多参数函数模板:
- 编译器是无法自动推导返回值类型的
- 可以从左向右部分指定类型参数
看代码:
template <typename T1, typename T2, typename T3>
T1 add(T2 a, T3 b)
{
T1 ret;
ret = static_cast<T1>(a + b);
return ret;
}
void main()
{
int c = 12;
float d = 23.4;
//cout << add(c, d) << endl; //error,无法自动推导函数返回值
cout<<add<float>(c, d)<< endl; //返回值在第一个类型参数中指定
cout<<add<int, int, float>(c, d) << endl;
system("pause");
}
结果:
2. 当函数模板遇上函数重载
函数模板跟普通函数一样,也可以被重载
- C++编译器优先考虑普通函数
- 如果函数模板可以产生一个更好的匹配,那么就选择函数模板
- 也可以通过空模板实参列表<>限定编译器只匹配函数模板
template <typename T>
void fun(T a)
{
cout << "void fun(T1 a)" << endl;
}
template <typename T1, typename T2>
void fun(T1 a, T2 b)
{
cout << "void fun(T1 a, T2 b)" << endl;
}
void fun(int a, float b)
{
cout << "void fun(int a, float b)" << endl;
}
void main()
{
int a = 0;
float b = 0.0;
fun(a);
fun(a, b); //普通函数void fun(int a, float b)已经能完美匹配,于是调用普通函数
fun(b, a); //这个调用,函数模板有更好的匹配,于是调用函数模板
fun<>(a, b); //限定只使用函数模板
system("pause");
}
结果:
3.类模板
同理,先骑自行车
template <typename T>
class Complex{
public:
//构造函数
Complex(T a, T b)
{
this->a = a;
this->b = b;
}
//运算符重载
Complex<T> operator+(Complex &c)
{
Complex<T> tmp(this->a + c.a, this->b + c.b);
return tmp;
}
void showMsg()
{
cout << "a:" << a << " b:" << b << endl;
}
private:
T a;
T b;
};
void main()
{
//对象的定义,必须声明模板类型,因为要分配内容
Complex<int> a(10, 20);
Complex<int> b(20, 30);
Complex<int> c = a + b;
c.showMsg();
system("pause");
}
结果:
其实有了函数模板的基础、类模板就相对好理解了,都是将具体类型模糊化。
这仅仅是基础,以后再深入,仅仅是为了让你能够看懂后面的文章而已。