C++模板

女生的网名这么多〃 提交于 2020-01-14 01:22:20

模板

C++ 模板

模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。前面提到过,多态体现了泛型编程的思想,其语法基础是虚函数和虚继承,那么模板同样是泛型编程必不可少的工具。

函数模板

通过函数重载的方式,可以简单实现同名函数针对不同参数及数据类型进行处理并且不产生冲突,缺点是编写的代码量偏大,函数模板可以很好地解决这个问题。

template<typename T> //模板的形式,T为类型名
//template<class T>
void function(T a)
{
	cout << a << endl;
}

基于模板编写的函数可以接受不同类型的参数,如果处理过程对参数类型没有明确要求与限制的情况下,可以大大减少编程工作量。另外模板也可以有多个参数,template< typename T,typename Y >。需要注意,定义了模板变量之后,函数中必须同时包含全部的模板参数类型。如下:

template<typename T,typename Y>
void fun(T t,Y y) //可用
void fun(T t,Y y,int c1) //可用
void fun(T t) //不可用
void fun(T t,int c1) //不可用

另外,template作为函数模板时,仅对临近的代码段生效,即一个模板无法对两个函数生效。
当然我们会遇到特殊情形,例如fun函数本身不支持对某些特定类型数据的处理能力,例如

template<typename T> //模板的形式,T为类型名

void function(T a)
{
    cout << a << endl;
}

该函数不能处理结构体,以及类数据,在此引入函数模板具体化概念,对特殊类型单独处理。

#include <iostream>

using namespace std;

struct Node
{
    int a = 1;
};

template<typename T> //模板的形式,T为类型名
void function(T a)
{
    cout << a << endl;
}

template<> void function<Node>(Node n) //函数模板具体化的形式
{
    cout << n.a << endl; //cout无法直接输出结构体类型
}

int main()
{
    Node n;
    Node& n1 = n;
    function(n1);

    return 0;
}

这样就可以对结构体类型的数据单独进行处理了。注意,模板默认可以传递所有类型的参数,但对于函数内部对数据类型产生的限制,推荐使用具体化的方式进行处理。
普通函数,模板具体化,模板按照优先级从高到底的顺序,当函数同名,参数列表相同的时候,会优先执行普通声明的函数,如果没有,则优先匹配模板具体化的函数,最后才会选择执行函数模板。

template<typename T>
void fun(T a) //优先级最低

template<> void fun<int>(int a) //优先级居中

void fun(int a) //优先级最高

最后介绍函数模板的实例化:

template void fun<int>(int a)

实际应用中,函数模板传入的参数类型会决定编译器在底层实现哪一种代码,如果提前实例化某一种类型,则默认在底层实现该数据类型对应的方法,直观效果不大,但可以提升工作效率,以及增强代码的可读性。

类模板

类模板的形式如下:

#include <iostream>

using namespace std;

template<typename T> //类模板参数可以有默认值,函数模板不行
class father
{
public:
    T a;
    father(T t)
    {
        a = t;
        cout << a <<endl;
    }

};


int main()
{
    father<char> c1('a');
    father<int> *c2 = new father<int>(2);
    //如果类模板声明的时候有默认值,则创建对象的时候<>内容可以缺省。
    delete c2;
    return 0;
}

注意,一旦使用类模板,在接下来的代码中遇到类名,其后必须带上模板参数列表。
类外实现模板类成员函数的写法:

void father<int>::fun()
{}//法1

template <typename T,typename Y>
void father::fun(T, Y)
{} //法2

继承的模板

先上代码:

#include <iostream>

using namespace std;

template<typename T>
class father
{
public:
    T a;
    father(T t)
    {
        a = t;
        cout << a <<endl;
    }

};

class son : public father<int> //数据类型任意
{
    son(int b) : father<int>(b) //父类构造函数有参数
    {}
};

template<typename T>
class son2 : public father<T> //将子类声明为模板类,可以处理通用数据类型。
{
	son2(T t) : father<T>(t)
	{}
};

int main()
{
    father<char> c1('a');
    father<int> *c2 = new father<int>(2);
    delete c2;
    return 0;
}

以上代码非常重要,建议在编译器环境下自行编写,解决问题。

多态的模板

多态的模板

#include <iostream>

using namespace std;

template<typename T>
class father
{
public:
    T a;
    father()
    {}
    virtual void fun()
    {}
    virtual ~father()
    {}
};

class son : public father<int>
{
public:
    son() : father<int>()
    {}
};

template<typename T>
class son2 : public father<T>
{
public:
    son2() : father<T>()
    {}
};

int main()
{
    father<int> *pf;
    pf = new son2<int>; //子类本身是模板,需要传递参数,且类型需要一致
    delete pf;

    pf = new son; //子类本身不是模板,无需传参数
    delete pf;

    return 0;
}

模板的类型是类

先上代码:

#include <iostream>

using namespace std;

template<typename T>
class A
{
public:
    T t;
    A(T a)
    {
        t = a;
    }
};

template<typename T>
class B
{
public:
    T a;
    B(T p) : a(p)
    {
        cout << p << endl;
    }
    /*
    B(A<char> &p)
    {
        cout << p.t << endl;
    }
    */
};

template<> class B<A<char>> //亲测模板类不能直接重载构造函数
{
public:
    A<char> a;
    B(A<char> &p) : a(p)
    {
        cout << p.t << endl;
    }
};

int main()
{
    cout << "ultimate test!" << endl;
    A<char> a('t');
    B<A<char>> b(a);

    return 0;
}

类模板我也理解得不是很透彻,mark来日再更。
一个写得很直观的博文C++模板

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!