我们看到这个标题是不是觉得有点纳闷?我们要学习的是数据结构和,并不是某门语言。比如 C++ 就支持泛型编程,那么我们为什么还要来讨论这个呢?我们先来看看数据结构的特点:1、专注于数据元素之间的关系;2、专注于特定结构之上的算法。数据结构并不关注数据元素的具体类型

        那么如何为数据结构的学习选择合适的语言呢?我们之前有见到过 C 语言版的数据结构,也有 C++ 版的数据结构。但是从耦合性的角度来看,支持泛型编程的语言最适合数据结构的学习。所谓泛型编程便指的是不考虑具体数据类型的编程方式。对于 Swap 函数可以考虑写成泛型写法,如下

void Swap(T& a, T& b)
{
    T t = a;
    a = b;
    b = t;
}

        Swap 泛型写法中的 T 不是一个具体的数据类型,而是泛指任意的数据类型,这样我们是不是就可以代码复用了,不用重复的搬砖了。泛型编程对应于 C++ 中的函数模板,它是一种特殊的函数可用不同类型进行调用。它看起来和普通函数很相似,其区别是类型可被参数化。函数模板格式如下

template < typename T >
void Swap(T& a, T& b)
{
    T t = a;
    a = b;
    b = t;
}

        下来我们来看看函数模板的语法规则:1、template 关键字用于声明开始进行泛型编程;2、typename 关键字用于声明泛指类型。如下图所示

泛型编程简介(三)_第1张图片   

        我们来看看函数模板的使用:1、自动类型推倒调用;2、具体类型显示调用。具体如下

int a = 0;
int b = 1;

Sawp(a, b);          // 自动推导

float c= 2;
float d = 3;

Swap(c, d);    // 显示调用

        我们下面还是以代码为例来进行说明

#include 

using namespace std;

template < typename T >
void Swap(T& a, T& b)
{
    T t = a;
    a = b;
    b = t;
}

template < typename T >
class Op
{
public:
    T process(T v)
    {
        return v * v;
    }
};

int main()
{
    int a = 1;
    int b = 2;
    
    Swap(a, b);
    
    cout << "a = " << a << ", " << "b = " << b << endl;
    
    double c = 0.01;
    double d = 0.02;
    
    Swap(d, c);
    
    cout << "c = " << c << ", " << "d = " << d << endl;
    
    Op opInt;
    Op opDouble;
    
    cout << "5 * 5 = " << opInt.process(5) << endl;
    cout << "0.5 * 0.5 = " << opDouble.process(0.5) << endl;
    
    return 0;
}

        我们来编译看看结果,是否如我们代码所写的那样

泛型编程简介(三)_第2张图片

        C++ 中的类模板是以相同的方式处理不同的类型,在类声明前使用 template 进行标识; 用于说明类中使用的泛指类型 T。类模板只能显示指定具体类型,是无法进行自动推导的;使用具体类型 定义对象。在上面的例子中,如果我们在第39, 40行不指定具体类型时,看看会发生什么?

泛型编程简介(三)_第3张图片

        报了一大堆错误,最后发现是没指定具体类型所导致的。通过对泛型编程的学习,总结如下:1、模板是泛型编程理论在 C++ 中的实现;2、函数模板支持参数的自动推导和显示指定;3、类模板在使用时只能显示指定类型;它非常适用于编写数据结构相关的代码。