泛型编程:编写与数据类型无关的逻辑代码,是代码复用的一种手段。

泛型这个词并不是通用的,在不同的语言实现中,具有不同的命名。在Java/Kotlin/C#中称为泛型(Generics),在ML/Scala/Haskell中称为Parametric Polymorphism,而在C++中被叫做模板(Template),比如最负盛名的C++中的STL。任何编程方法的发展一定是有其目的,泛型也不例外。

泛型的主要目的是加强类型安全和减少强制转换的次数。

 

为什么要用泛型编程:

       当我们希望可以用同一个函数处理不同类型的参数时(比如写一个加法函数,可以处理各种不同类型的数据)都有哪些方法呢?

1、函数重载(同一作用域;函数名相同;参数列表不同)

缺点:

        a、只要有新类型出现,就必须添加对应的函数

        b、除了类型外,所有的函数体都相同,代码的复用率太低

        c、如果只是返回类型不同,函数重载不能实现

        d、一个方法有问题,所有的方法都有问题,不好维护

2、使用公共基类,将所有通用的代码放在公共的基类里面(通过继承的方式将其复用)

缺点:

        a、借助公共基类来编写通用代码将失去类型检查的优点

        b、对于以后实现的许多类,都必须继承自某个特定的基类,代码维护更贱困难

3、使用特殊的预处理程序(使用宏)

缺点:

        a、不是函数,不会进行类型检测,安全性不高

        b、不能调试

        c、经常会有副作用(除非将每一项都打上括号)

        d、直接替换的方式,如果多次使用会使代码变得越来越长

接下来要介绍的另外一种新的方法--------泛型编程

 

模板形参名在同一模板形参列表中只能使用一次。所有模板前面必须加上class或者typename.

【C++】泛型编程和模板_实例化

举个例子

#include <iostream>
using namespace std;

template <class T>
T Add(T left, T right)
{
return left + right;
}

int main()
{
cout << Add(1, 2)<<endl;//T为int
cout << Add(1.1, 2.2)<<endl;//T为double

//cout << Add(1, 2.2) << endl;
cout << Add(1, (int)2.2)<<endl;//T为int
cout << Add<int>(1, 2.2)<<endl;//显示实例化

return 0;
}

上边这个例子,当不将主函数中的第三行代码注释的话是会因为两个实参的类型不同而报错,遇到这种情况,我们可以用强制类型转化或显示实例化的方式解决。

注释前

将其注释后通过编译,没有任何错误。

注意,模板被编译了两次,一次T为int ,一次T为double。通过函数调用给出的实参来确实能够模板形参 T 的类型和值的过程称为模板的实参推演。