C++语言- 泛型编程之类模板(详解)
小标 2018-07-25 来源 : 阅读 1281 评论 0

摘要:本文主要向大家介绍了C++语言- 泛型编程之类模板(详解),通过具体的内容向大家展示,希望对大家学习C++语言有所帮助。

本文主要向大家介绍了C++语言- 泛型编程之类模板(详解),通过具体的内容向大家展示,希望对大家学习C++语言有所帮助。

类模板介绍

和函数模板一样,将泛型思想应用于类.

编译器对类模板处理方式和函数模板相同,都是进行2次编译

类模板通常应用于数据结构方面,使得类的实现不在关注数据元素的具体类型,而只关注需要实现的功能

比如: 数组类,链表类,Queue类,Stack类等

 

使用方法

· 通过template关键字来声明,然后通过typename关键字来定义模板类型,如下图所示:

 

 

类模板的使用

· 定义对象时,必须指定类模板类型,因为编译器无法推导类型

· 使用具体类型<Type>来定义对象

如下图所示:

 

 

初探类模板

写一个类模板,实现不同类型的加减乘除

 

#include <iostream>

#include <string>

using namespace std;

 

template < typename T >class Operator

{public:

     T add(T a, T b)

    {

        return a + b;

    }

 

     T minus(T a, T b)

    {

        return a - b;

    }

 

     T multiply(T a, T b)

    {

        return a * b;

    }

 

     T divide(T a, T b)

    {

        return a / b;

    }

};
string operator-(string& l, string& r)   //由于string类没有重载减号操作符,所以我们自定义一个

{

    return "Minus";

}

int main()

{

    Operator<int>  op1;            //定义对象时,需要指定类模板类型

    cout << op1.add(1, 2) << endl;          

 

    Operator<string>  op2;         //定义对象时,需要指定类模板类型

    cout << op2.add("D.T.", "Software") << endl;

    cout << op2.minus("D.T", "Software") << endl;

    return 0;

}

 

运行打印:

3

D.T. Software

Minus

 

类模板的工程应用

· 类模板必须在.h头文件中定义

· 类模板的成员函数不能分开在不同的文件中实现

· 类模板外部定义的成员函数,和模板函数一样,还需要加上模板template <typename T>声明,以及结构体<T>声明

接下来,我们便修改上面代码定义的Operator类模板,只需要写Operator.h文件即可:

 

#ifndef  _OPERATOR_H#define _OPERATOR_H

 

template < typename T >class Operator

{public:

    T add(T a, T b);

    T minus(T a, T b);

    T multiply(T a, T b);

    T divide(T a, T b);

};

 

template < typename T >           //外部定义的成员函数,都需要加上模板声明

T  Operator<T> :: add(T a, T b)  //同时加上结构体<T>声明

{

       return a+b;

}

 

template < typename T >          

T  Operator<T> :: minus(T a, T b)

{

       return a-b;

}

template < typename T >          

T  Operator<T> :: multiply(T a, T b)

{

       return a*b;

}

 

template < typename T >          

T  Operator<T> :: divide(T a, T b)

{

       return a/b;

}

#endif

 

 

多参数类模板

类模板可以定义任意多个不同的类型参数,同时还要必须指定每个模板参数

例如:

 

template < typename T1,typename T2 >class Operator

{public:

    void add(T1 a, T2 b);

};

 

template < typename T1,typename T2 >void Operator<T1,T2 > :: add(T1 a, T2 b)

{

        cout<<a+b<<endl;

}

int main()

{

    Operator<int,float> op1;                 //定义op1对象时,必须指定类模板类型

    op1.add(2,2.1);                                  //4.1

    return 0;

}

 

运行打印:

4.1

从结果来看,上面的类模板好像已经实现了add加法运算.但是却不能支持指针类型.

其实,类模板也可以像函数重载一样, 类模板通过特化的方式可以实现特殊情况.

 

类模板特化

· 表示可以存在多个相同的类名,但是模板类型都不一致(和函数重载的参数类似)

· 特化类型有完全特化和部分特化两种类型

· 完全特化表示显示指定类型参数,模板声明只需写成template<>,并在类名右侧指定参数,比如:

 

template < typename T1,typename T2 >  //声明的模板参数个数为2个class Operator                        //正常的类模板

{public:

        void add(T1 a, T2 b)

       {

              cout<<a+b<<endl;

       }

};

 

template <>                           //不需要指定模板类型,因为是完全特化的类模板class Operator< int , int>           //指定类型参数,必须为2个参数,和正常类模板参数个数一致

{                                               

public:

void add(int a, int b)

 

{

 

cout<<a+b<<endl;

 

}

 

};

int main()

 

{

 

       Operator<int,int> Op1;        //匹配完全特化类模板:class Operator< int,int>

       Operator<int,float> Op2;     //匹配正常的类模板

 

       return 0;

 

}

 

· 部分特化表示通过特定规则约束类型参数,模板声明和类似,并在类名右侧指定参数,比如:

 

template < typename T1,typename T2 >           //声明的模板参数个数为2个class Operator                                 //正常的类模板

{public:

        void add(T1 a, T2 b)

       {

              cout<<a+b<<endl;

       }

};

 

 

 

template < typename T >          //有指定模板类型以及指定参数,所以是部分特化的类模板             class Operator< T* ,T*>          //指定类型参数,必须为2个参数,和正常类模板参数个数一致

{public:

  void add(T* a, T* b)

  {

              cout<<*a+*b<<endl;

  }

};

int main()

{

     Operator<int*,int*> Op1;            //匹配部分特化: class Operator< T* ,T*>

     Operator<int,float> Op2;           //匹配正常的类模板: class Operator     return 0;

}

 

· 编译时,会根据对象定义的类模板类型,首先去匹配完全特化,再来匹配部分特化,最后匹配正常的类模板.

 

初探类模板特化

 

#include <iostream>

using namespace std;

 

template < typename T1,typename T2 >  class Operator                                            //正常的类模板

{public:

        void add(T1 a, T2 b)

       {

              cout<<"add(T1 a, T2 b)"<<endl;

              cout<<a+b<<endl;

       }

};

 

template < typename T >                              class Operator<T,T>                                //部分特化的类模板,当两个参数都一样,调用这个

{public:

         void add(T a, T b)

       {

              cout<<"add(T a, T b)"<<endl;

              cout<<a+b<<endl;

       }

};

 

template < typename T1,typename T2 >  class Operator<T1*,T2*>                                   //部分特化的类模板,当两个参数都是指针,调用这个

{public:

        void add(T1* a, T2* b)

       {

              cout<<"add(T1* a, T2* b)"<<endl;

              cout<<*a+*b<<endl;

       }

};

 

template < >  class Operator<void*,void*>                             //完全特化的类模板,当两个参数都是void*,调用这个

{public:

        void add(void* a, void* b)

       {

              cout<<"add(void* a, void* b)"<<endl;

              cout<<"add void* Error"<<endl;                 //void*无法进行加法

       }

};

int main()

{

       int *p1 = new int(1);

       float *p2 = new float(1.25);

 

       Operator<int,float>  Op1;        //匹配正常的类模板:class Operator      

       Op1.add(1,1.5);

 

       Operator<int,int>  Op2;          //匹配部分特化的类模板:class Operator<T,T>

       Op2.add(1,4);

 

       Operator<int*,float*>  Op3;      //匹配部分特化的类模板:class Operator<T1*,T2*>      

       Op3.add(p1,p2);

 

       Operator<void*,void*>  Op4;      //匹配完全特化的类模板:class Operator<void*,void*>

       Op4.add(NULL,NULL);  

 

       delete p1;

       delete p2;

 

       return 0;

}

 

运行打印:

 

add(T1 a, T2 b)2.5

 

add(T a, T b)5

 

add(T1* a, T2* b)2.25

 

add(void* a, void* b)

add void* Error

 

 

数值型模板参数

之前,我们学习的模板参数都是带泛型的(表示不同类型),其实模板参数也可以是数值型参数,如下图所示:

 

 

 

· 数值型模板参数必须在编译时被唯一确定

比如: 变量在运行期间是可变的,所以不能作为模板参数.以及浮点数(不精确),类对象(可变)等等.

 

接下来,我们便通过数值参数的类模板来求 1+2+3+...+N的值

代码如下所示:

 

template < int N >class Sum

{public:

    static const int VALUE = Sum<N-1>::VALUE + N;              //定义静态常量并赋值

};

template < >class Sum < 1 >

{public:

    static const int VALUE = 1;

};

int main()

{

    cout << "1 + 2 + 3 + ... + 10 = " << Sum<10>::VALUE << endl;

    cout << "1 + 2 + 3 + ... + 100 = " << Sum<100>::VALUE << endl;

    return 0;

}

 

运行打印:

1 + 2 + 3 + ... + 10 = 551 + 2 + 3 + ... + 100 = 5050

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程