摘要:本文主要向大家介绍了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+频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号