c++模板

一.泛型编程

泛型编程即编写一种与类型无关的逻辑代码,是一种复用.
二.模板
模板分为模板函数模板类.
  • 模板函数
我们经常使用的swap函数,用来交换两个同类型的参数

Swap(int* a,int*b); //用来交换两个整形
Swap(char* a,char* b); //用来交换两个字符
Swap(float* a,float* b); //用来交换两个浮点型
...
这样看下去,如果我们有n中类型需要交换,我们就需要写n个Swap函数
C++就是考虑到这一点,采用了模板,实现一堆逻辑相同,只有参数不相同的代码,极大的复用了代码,使本该由程序员自己编写的代码,模板在底层为我们实现
模板函数格式

template <class 形参名1,class 形参名2,class 形参名3...>
返回类型 函数名(参数列表)
{
    //TODO
}
上面的 class 可是用 typename 替换
下面我们看一下Swap模板函数的实现

#include <iostream>
using namespace std;
#include <stdio.h>

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

int main()
{
    int a = 1, b = 2;
    printf("before a = %d,b = %d\n",a,b);
    Swap(a,b);
    printf("after a = %d,b = %d\n",a,b);
    char ch1 = 'a',ch2 = 'b';
    printf("before ch1 = %c,ch2 = %c\n",ch1,ch2);
    Swap(ch1,ch2);
    printf("after ch1 = %c,ch2 = %c\n",ch1,ch2);
    float f1 = 3.14, f2 = 6.28;
    printf("before f1 = %f,f2 = %f\n",f1,f2);
    Swap(f1,f2);
    printf("after f1 = %f,f2 = %f\n",f1,f2);
    return 0;
}
运行结果:

汇编底层实现

我们可以看到,交换三种类型的参数,Swap在汇编层分别调用了三个函数,这就证明编译器在底层为我们实现了三个参数不同的函数,用来做交换
其实,编译器会处理代码,在发现调用模板参数时,为我们自动生成一份对应参数的函数代码,这几个函数构成了重载.
注意:
在不调用模板参数时,编译器并不会形成代码,只会检查模板的框架符不符合语言要求,一旦被调用才回去实例化出代码.


我把main函数中调所有调用模板的函数屏蔽掉,编译代码,显示成功,可见这里并没有实例化出代码,编译器自然检测不到这里的错误
但是一旦我们调用,结果就不一样了

  • 模板类
以普通顺序表举例:
以前我们定义顺序表的时候都会这样定义:

typedef int DataType; //指定出顺序表中的类型,这里为int
class Vector
{
public:
     Vector();
     ~Vector();
     Vector(const Vector& v);
     Vector& operator=(Vector v);
     size_t Size()const;
     size_t Capacity()const;
     void Expand(size_t n);
     void PushBack(DataType value); //使用类型的时候用 typedef出来的DataType
     void PopBack();
     void Insert(size_t pos, DataType value);
     void Erase(size_t pos);
     void Show();
protected:
     DataType* _first;
     DataType* _finish;
     DataType* _endofstorage;
};
以上的定义方法使得我们的顺序表中只可以存储int类型的变量
下面我们用模板来定义顺序表
定义格式

template <class 形参1,class 形参2,...> 
类名 
{
     //TODO 
};
这里的class也可以用typename替换

template <class T> //指定顺序表中的类型,这里为泛型T
class Vector
{
public:
     Vector();
     ~Vector();
     Vector(const Vector<T>& v);
     Vector<T>& operator = (Vector<T> v);
     void Expand(size_t n);
     void PushBack(T value); //使用类型的时候直接使用 T
     void PopBack();
     void Insert(size_t pos, T value);
     void Erase(size_t pos);
     void Show();
protected:
     T* _first;
     T* _finish;
     T* _endofstorage;
};
这里需要分清两个概念
Vectore    ->    类名(声明构造函数或者析构函数时我们需要的是类名)
Vectore<T>    ->    类型(声明赋值运算符的重载时,我们返回值应该是一个类型)
声明和定义分离时,模板函数的定义

template <class T>
Vector<T>::Vector() :_first(NULL), _finish(NULL), _endofstorage(NULL)
{}

template <class T>
Vector<T>::~Vector()
{
     delete[] _first;
     _first = _finish = _endofstorage = NULL;
}

template <class T>
Vector<T>::Vector(const Vector<T>& v)
{
     size_t size = v.Size();
     _first = new T[Capacity()];
     size_t i = 0;
     for (; i < size; ++i)
     {
           _first[i] = v._first[i];
     }
     _finish = _first + size;
     _endofstorage = _first + v.Capacity();
}
调用方法

int main()
{
    Vector<int> v1;
    Vector<char> v2;
    return 0;
}

















展开阅读全文

没有更多推荐了,返回首页