C++—模板(2)类模板与其特化
我们以顺序表为例来说明,普通顺序表的定义如下:
typedef int DataType;
//typedef char DataType;
class SeqList
{
private :
DataType* _data ;
int _size ;
int _capacity ;
} ;
模板类也是模板, 必须以 关键字templ ate开头, 后接模板形参表。 模板类一般格式如下:
template<class 形参名 1, class 形参名 2, . . . class 形参名 n>
class 类名
{ . . . } ;
// 以模板方式实现动态顺序表
template<typename T>
class SeqList
{
public :
SeqList() ;
~ SeqList() ;
private :
int _size ;
int _capacity ;
T* _data ;
} ;
template <typename T>
SeqList <T>: : SeqList()
:
_size()
, _capacity()
, _data(new T[ _capacity] )
{}//注意模板类的类型不是SeqList
template <typename T>
SeqList <T>: : ~ SeqList()
{
delete [] _data ;
}
void test1()
{
SeqList<int > sl1;
SeqList<double > sl2;
}

【 模板类的实例化】
只 要有一种不同的类型, 编译器就会实例化出一个对应的类。
SeqList<int > sl1;
SeqList<double > sl2;
当定义上述两种类型的顺序表时, 编译器会使用int和double分别代替模板形参, 重新编写SeqList类, 最后创建名 为SeqList<int>和SeqList<double>的类。
模板参数--实现容器适配器
template <typename T>
class SeqList
{p
rivate :
int _size ;
int _capacity ;
T* _data ;
} ;
// template <class T, class Container>
template <class T, class Container = SeqList<T> > // 缺省参数
class Stack
{
public :
void Push (const T& x) ;
void Pop () ;
const T& Top() ;
bool Empty () ;
private :
Container _con ;
} ;
void Test()
{
Stack<int> s1;
Stack<int , SeqList<int>> s2 ;
// 思考下面这种使用场景会怎样?
Stack<int , SeqList<char>> s3 ;
}
为了避免上述问题的存在用下面的方法:
模板的模板参数--容器适配器
template <typename T>
class SeqList
{p
rivate :
int _size ;
int _capacity;
T* _data ;
} ;
// template <class T, template<class> class Container>
template <class T, template<class> class Container = SeqList> // 缺省参数
class Stack
{
public :
void Push(const T& x ) ;
void Pop() ;
const T& Top() ;
bool Empty() ;
private :
Container<T > _con;
} ;
void Test()
{
Stack<int> s1;
Stack<int , SeqList> s2;
}

非类型的类模板参数
// 静态顺序表
//template<typename T, size_t MAX_SIZE>
template <typename T, size_t MAX_SIZE = > //带缺省模板参数
class SeqList
{
public :
SeqList() ;
private :
T _array [MAX_SIZE] ;
int _size ;
} ;
template <typename T, size_t MAX_SIZE>
SeqList <T, MAX_SIZE>: : SeqList()
: _size()
{}
void Test()
{
SeqList<int> s1;
SeqList<int , > s2;
}
注意: 浮点数和类对象是不允许作为非类型模板参数的。
类模板的特化
类模板的特化:与函数模板类似,当类模板内需要对某些类型进行特别处理时,使用类模板的特化。例如:
// general version
template<class T>
class Compare
{
public:
static bool IsEqual(const T& lh, const T& rh)
{
std::cout <<"in the general class..." <<std::endl;
return lh == rh;
}
};
// specialize for float
template<>
class Compare<float>
{
public:
static bool IsEqual(const float& lh, const float& rh)
{
std::cout <<"in the float special class..." <<std::endl; return std::abs(lh - rh) < 10e-;
}
};
// specialize for double
template<>
class Compare<double>
{
public:
static bool IsEqual(const double& lh, const double& rh)
{
std::cout <<"in the double special class..." <<std::endl; return std::abs(lh - rh) < 10e-;
}
};
int main(void)
{
Compare<int> comp1;
std::cout <<comp1.IsEqual(, ) <<std::endl;
std::cout <<comp1.IsEqual(, ) <<std::endl; Compare<float> comp2;
std::cout <<comp2.IsEqual(3.14, 4.14) <<std::endl;
std::cout <<comp2.IsEqual(, ) <<std::endl; Compare<double> comp3;
std::cout <<comp3.IsEqual(3.14159, 4.14159) <<std::endl;
std::cout <<comp3.IsEqual(3.14159, 3.14159) <<std::endl;
return ;
}

全特化
还是以顺序表为例说明
全特化
template <typename T>
class SeqList
{
public :
SeqList() ;
~ SeqList() ;
private :
int _size ;
int _capacity ;
T* _data ;
} ;
template<typename T>
SeqList <T>: : SeqList()
: _size()
, _capacity()
, _data(new T[ _capacity] )
{
cout<<"SeqList<T>" <<endl;
}
template<typename T>
SeqList <T>: : ~ SeqList()
{
delete[] _data ;
}
template <>
class SeqList <int>
{
public :
SeqList(int capacity) ;
~ SeqList() ;
private :
int _size ;
int _capacity ;
int* _data ;
} ;
// 特化后定义成员 函数不再需要模板形参
SeqList <int>: : SeqList(int capacity)
: _size()
, _capacity(capacity )
, _data(new int[ _capacity] )
{
cout<<"SeqList<int>" <<endl;
}
// 特化后定义成员 函数不再需要模板形参
SeqList <int>: : ~ SeqList()
{
delete[] _data ;
}
void test1 ()
{
SeqList<double > sl2;
SeqList<int > sl1() ;
}
偏特化( 局部特化)
template <typename T1, typename T2>
class Data
{
public :
Data() ;
private :
T1 _d1 ;
T2 _d2 ;
} ;
template <typename T1, typename T2>
Data<T1 , T2>: : Data()
{
cout<<"Data<T1, T2>" <<endl;
}
// 局部特化第二个参数
template <typename T1>
class Data <T1, int>
{
public :
Data() ;
private :
T1 _d1 ;
int _d2 ;
} ;
template <typename T1>
Data<T1 , int>: : Data()
{
cout<<"Data<T1, int>" <<endl;
}
下面的例子可以看出, 偏特化并不仅仅是指特化部分参数, 而是针对模板参数更进一步的条件限制所设计出来的一个特化版本。
// 局部特化两个参数为指针类型
template <typename T1, typename T2>
class Data <T1*, T2*>
{
public :
Data() ;
private :
T1 _d1 ;
T2 _d2 ;
T1* _d3 ;
T2* _d4 ;
} ;
template <typename T1, typename T2>
Data<T1 *, T2*>: : Data()
{
cout<<"Data<T1*, T2*>" <<endl;
}
// 局部特化两个参数为引 用
template <typename T1, typename T2>
class Data <T1&, T2&>
{
public :
Data(const T1& d1, const T2& d2) ;
private :
const T1 & _d1;
const T2 & _d2;
T1* _d3 ;
T2* _d4 ;
} ;
template <typename T1, typename T2>
Data<T1 &, T2&>: : Data(const T1& d1, const T2& d2)
: _d1(d1 )
, _d2(d2 )
{
cout<<"Data<T1&, T2&>" <<endl;
}
void test2 ()
{
Data<double , int> d1;
Data<int , double> d2;
Data<int *, int*> d3;
Data<int&, int&> d4(, ) ;
}
模板的全特化和偏特化都是在已定义的模板基础之上,不能单独存在。
关于特化的总结:
特化的分类
针对特化的对象不同,分为两类:函数模板的特化和类模板的特化
函数模板的特化:当函数模板需要对某些类型进行特化处理,称为函数模板的特化。
类模板的特化:当类模板内需要对某些类型进行特别处理时,使用类模板的特化。
特化整体上分为全特化和偏特化
全特化就是模板中模板参数全被指定为确定的类型。全特化也就是定义了一个全新的类型,全特化的类中的函数可以与模板类不一样。
偏特化就是模板中的模板参数没有被全部确定,需要编译器在编译时进行确定。
全特化的标志就是产生出完全确定的东西,而不是还需要在编译期间去搜寻适合的特化实现,貌似在我的这种理解下,全特化的 东西不论是类还是函数都有这样的特点,
模板函数只能全特化,没有偏特化(重载)。
模板类是可以全特化和偏特化的。
很多时候,我们既需要一个模板能应对各种情形,又需要它对于某个特定的类型(比如bool)有着特别的处理,这种情形下特化就是非常必要的。
模板总结
【 优点】
模板复用了 代码, 节省资源, 更快的迭代开发, C++的标准模板库(STL) 因此而产生。
增强了 代码的灵活性。
【 缺点】
模板让代码变得凌乱复杂, 不易维护, 编译代码时间变长。
出现模板编译错误时, 错误信息非常凌乱, 不易定位错误。
C++—模板(2)类模板与其特化的更多相关文章
- 【校招面试 之 C/C++】第2题 函数模板、类模板、特化、偏特化
1.C++模板 说到C++模板特化与偏特化,就不得不简要的先说说C++中的模板.我们都知道,强类型的程序设计迫使我们为逻辑结构相同而具体数据类型不同的对象编写模式一致的代码,而无法抽取其中的共性,这样 ...
- C++解析(26):函数模板与类模板
0.目录 1.函数模板 1.1 函数模板与泛型编程 1.2 多参数函数模板 1.3 函数重载遇上函数模板 2.类模板 2.1 类模板 2.2 多参数类模板与特化 2.3 特化的深度分析 3.小结 1. ...
- [Reprint] C++函数模板与类模板实例解析
这篇文章主要介绍了C++函数模板与类模板,需要的朋友可以参考下 本文针对C++函数模板与类模板进行了较为详尽的实例解析,有助于帮助读者加深对C++函数模板与类模板的理解.具体内容如下: 泛型编程( ...
- C++_进阶之函数模板_类模板
C++_进阶之函数模板_类模板 第一部分 前言 c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来 ...
- 学习C++模板,类模板
当我们使用向量时,会经常使用形如:vector<int> a的式子.这个表达式就是一个类模板实例化的例子,vector是一个类模板,我们给他传递模板参数(见<>里),然后创建一 ...
- C++复习:函数模板和类模板
前言 C++提供了函数模板(function template).所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表.这个通用函数就称为函数模板.凡是函数体 ...
- C++ 函数模板与类模板(使用 Qt 开发编译环境)
注意:本文中代码均使用 Qt 开发编译环境,如有疑问和建议欢迎随时留言. 模板是 C++ 支持参数化程序设计的工具,通过它可以实现参数多态性.所谓参数多态性,就是将程序所处理的对象的类型参数化,使得一 ...
- C++ 模板常见特性(函数模板、类模板)
背景 C++ 是很强大,有各种特性来提高代码的可重用性,有助于减少开发的代码量和工作量. C++ 提高代码的可重用性主要有两方面: 继承 模板 继承的特性我已在前面篇章写过了,本篇主要是说明「模板」的 ...
- C++进阶-1-模板基础(函数模板、类模板)
C++进阶 模板 1.1 函数模板 1 #include<iostream> 2 using namespace std; 3 4 // 模板 5 6 // 模板的简单实例 7 // 要求 ...
- IDEA自定义liveTemplates(方法模板、类模板)
IDEA自定义liveTemplates(方法模板.类模板) 前言,搞这个模板有何意义? 降低大家写方法注释的成本,统一风格.有时候不是开发同学不爱写注释,而是没有合适的载体和空间. IDEA模板设置 ...
随机推荐
- 《玩转spring全家桶》学习笔记-------------丁雪丰
一.spring 课程介绍 1.初识spring 2.数据操作 3.web开发 4.spring boot 5.spring cloud 二.初识spring Spring Boot.Spring C ...
- Magento 2 自带模态的应用
Modal widget in Magento 2 Magento 2 自带模态的应用 使用magento 2 的自带模态组件,以下代码只供参考使用. 1,DOM >模态块与触发元素 .pthm ...
- python学习日记(正则表达式)
定义 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配. Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式. re 模块使 Pyth ...
- 洛谷P1066 2^k进制数(题解)(递推版)
https://www.luogu.org/problemnew/show/P1066(题目传送) (题解)https://www.luogu.org/problemnew/solution/P106 ...
- python图形用户
1)使用GUI 1.GUI:Graphical user interface 2.tkinter:GUI libary for Python自带的库 3.GUI:Example 2)Ubuntu18. ...
- ZooKeeper-API 监听
以服务动态上下线通知为例 Client 监听服务器状态 public class DistributeClient { private String connectString = "127 ...
- 人工智能初识(百度ai)
目前的人工智能做了什么? 语音识别:小米的小爱同学,苹果的siri,微软的Cortana语音合成:小米的小爱同学,苹果的siri,微软的Cortana图像识别:交通摄像头拍违章,刷脸解锁手机等视频识别 ...
- 通过Hack方式实现SDC中Stage配置联动刷新
目录 问题描述 如何从外部获取下拉列表参数 如何实现根据下拉列表选项动态刷新 总结 问题描述 最近项目组准备开发一个IoT平台项目,需要使用到StreamSets DataCollector组件进行数 ...
- Python包中 __init__.py文件的作用
原创连接 https://www.cnblogs.com/AlwinXu/p/5598543.html Python包中 __init__.py文件的作用 在创建python包的过程中,IDE都会在包 ...
- PMP知识点(一)——风险登记册
一.Reference: [管理心得之四十八]<风险登记册>本身的风险 问题日志与风险登记册的区别与联系 PMBOK重要概念梳理之二十六 风险登记册 风险登记单-MBAlib 二.Atta ...