C++ 函数模板与类模板

1-1 为什么要一用函数模板呢。

#include <iostream>
using namespace std;
/*
void myswap(int &a, int &b)
{
    int t = a;
    a = b;
    b = t;
}

void myswap(char &a, char &b)
{
    char t = a;
    a = b;
    b = t;
}
*/

//template 关键字告诉C++编译器 我要开始泛型了.你不要随便报错  
//数据类型T 参数化数据类型
template <typename T>
void myswap(T &a, T &b)
{
    T t;
    t = a;
    a = b;
    b = t;
}

void main()
{
    //char a = 'c';

    int  x = 1;
    int  y = 2;
    myswap(x, y); //自动数据类型 推导的方式 

    float a = 2.0;
    float b = 3.0;

    myswap(a, b); //自动数据类型 推导的方式 
    myswap<float>(a, b); //显示类型调用 

    cout<<"hello..."<<endl;
    system("pause");
    return ;
}

1-2 函数模板可以做函数的参数

#include <iostream>
using namespace std;

template<typename T, typename T2>
void sortArray(T *a, T2 num)
{
    T tmp ;
    int i, j ;
    for (i=0; i<num; i++)
    {
        for (j=i+1; j<num; j++)
        {
            if (a[i] < a[j])
            {
                tmp = a[i];
                a[i] = a[j];
                a[j] = tmp;
            }
        }
    }
}

template<class T>
void pirntArray(T *a, int num)
{
    int i = 0;
    for (i=0; i<num; i++)
    {
        cout<<a[i]<<" ";
    }
}

void main()
{
    int num = 0;
    char a[] = "ddadeeettttt";
    num = strlen(a);

    printf("排序之前\n");
    pirntArray<char>(a, num);

    sortArray<char, int>(a, num); //显示类型调用 模板函数 <>
    printf("排序之后\n");
    pirntArray<char>(a, num);
    cout<<"hello..."<<endl;
    system("pause");
    return ;
}

1-3 函数模板遇上函数重载

函数模板和普通函数区别结论:
函数模板不允许自动类型转化
普通函数能够进行自动类型转换

函数模板和普通函数在一起,调用规则:
1 函数模板可以像普通函数一样被重载
2 C++编译器优先考虑普通函数
3 如果函数模板可以产生一个更好的匹配,那么选择模板

不妨看下面的案例分析一波:

#include <iostream>
using namespace std;

template <typename T>
void myswap(T &a, T &b)
{
    T t;
    t = a;
    a = b;
    b = t;
    cout<<"myswap 模板函数do"<<endl;
}

void myswap(char &a, int &b)
{
    int t;
    t = a;
    a = b;
    b = t;
    cout<<"myswap 普通函数do"<<endl;
}

void main()
{
    char cData = 'a';
    int  iData = 2;

    //myswap<int>(cData, iData);  //结论 函数模板不提供隐式的数据类型转换  必须是严格的匹配

    myswap(cData, iData); 
    //myswap(iData, cData);

    cout<<"hello..."<<endl;
    system("pause");
    return ;
}

1-4 函数模板机制结论:

编译器并不是把函数模板处理成能够处理任意类的函数
编译器从函数模板通过具体类型产生不同的函数
编译器会对函数模板进行两次编译
在声明的地方对模板代码本身进行编译;在调用的地方对参数替换后的代码进行编译。

2.1 可以这样声明和使用类模板:

1) 先写出一个实际的类。由于其语义明确,含义清楚,一般不会出错。
2) 将此类中准备改变的类型名(如int要改变为float或char)改用一个自己指定的虚拟类型名.
3) 在类声明前面加入一行,格式为:

 template <class 虚拟类型参数>

如:

 template <class numtype> //注意本行末尾无分号
    class Compare
    {…}; //类体

4) 用类模板定义对象时用以下形式:

   类模板名<实际类型名> 对象名;
    类模板名<实际类型名> 对象名(实参表列);

如:

    Compare<int> cmp;
    Compare<int> cmp(3,7);

5)如果在类模板外定义成员函数,应写成类模板形式:

   template <class 虚拟类型参数>
      函数类型 类模板名<虚拟类型参数>::成员函数名(函数形参表列) {…}

2.2 关于类模板的几点说明:

1) 类模板的类型参数可以有一个或多个,每个类型前面都必须加class,如:

  template <class T1,class T2>
    class someclass
    {…};

在定义对象时分别代入实际的类型名,如:

    someclass<int,double> obj;

2) 和使用类一样,使用类模板时要注意其作用域,只能在其有效作用域内用它定义对象。
3) 模板可以有层次,一个类模板可以作为基类,派生出派生模板类。

2.3 类模板在项目开发中的应用

小结
 模板是C++类型参数化的多态工具。C++提供函数模板和类模板。
 模板定义以模板说明开始。类属参数必须在模板定义中至少出现一次。
 同一个类属参数可以用于多个模板。
 类属参数可用于函数的参数类型、返回类型和声明函数中的变量。
 模板由编译器根据实际数据类型实例化,生成可执行代码。实例化的函数。
模板称为模板函数;实例化的类模板称为模板类。
 函数模板可以用多种方式重载。
 类模板可以在类层次中使用 。

猜你喜欢

转载自blog.csdn.net/qq_39818571/article/details/78444330