1、所谓泛型编程就是独立于任何特定类型的方式编写代码,使用泛型程序时我们需要提供具体程序实例所操作的类型或值。模板是泛型的编程基础,使用模板时可以无须了解模板的定义。
2、在泛型编程中,我们所编写的类和函数能够多态的用于跨越编译时不相关的类型,一个类或者函数可以用来操作多种类型的对象
3、在C++中模板是泛型的编程基础,模板是创建类或函数的蓝图或公式
4、函数模板是一个独立于类型的函数,可以作为一种方式,产生函数的特定类型版本
5多态性:
1> 继承、虚函数、完成了运行时的多态性
2> 函数模板和函数重载完成了编译时的多态性
函数模板
1、函数模板的定义
//T 称为模板形参表,多个形参之间用逗号分隔
//模板形参表,表示可以在类或者函数定义中使用的类型或值
//T究竟表示那个实际类型由编译器根据所用的函数来确定
//模板形参可以是表示类型的类型实参,也可以是表示常量表达式的非类型实参
//类型形参跟在关键字class或者typename 之后,这里class和typename没有区别
template
int compare(T v1,T v2)
{
if(v1
if(v1>v2) return 1;
return 0;
}
2、函数模板的使用
1> 函数模板的形参的实际类型可以由编译器自己推测:compare(0,1)、comapre(1.0,2.0)
2>认为指定函数模板形参的实际类型:compare(0,1)、compare(1.0,2.0)
3、函数模板重载、函数模板的特化
特化:对函数模板形参进行一定的约束,约束在某个方面是偏特化,确定一个形参类型是部分特化,模
板形参的实际类型全部确定下来是全部特化
1> 模板的偏特化:
template
int compare(T* v1,T* v2)
{
if(*v1<*v2) return -1;
if(*v1>*v2) return 1;
return 0;
}
2> 模板的部分特化
template
int compare(int* v1,T* v2)
{
if(*v1<*v2) return -1;
if(*v1>*v2) return 1;
return 0;
}
3> 模板的全部特化
template<> //有这个表示说明是模板函数,当该模板没有用到时就不会被编译成对应的二进制
int compare(int* v1,int* v2)
{
if(*v1<*v2) return -1;
if(*v1>*v2) return 1;
return 0;
}
4、inline 函数模板
函数模板可以用与非模板函数一样的方式声明为inline
template inline int compare(T v1,Tv2);
类模板
1、类模板也是模板,也需要以template 开头,后接模板形参表
template
class queue
{
public:
queue();
type& front();
void push(type& );
}
2、在类和类成员的定义中,可以使用模板形参作为类型或值的占位符,在使用这些类的时候再提供哪些类型或值
3、模板的使用
1> 与函数模板的使用不同的是,使用类模板的时候必须显示的指定模板形参类型
queue qi; queue qs;
4、形参
1> 像函数模板一样,程序员为模板形参选择的名字没有本质的含义
2> 可以给模板形参赋予唯一含义的是:类型形参(未知类型)或者非类型形参(未知值)
3> 模板形参的名字作用域为:声明模板形参开始到模板声明或定义的结束
4> 作为模板形参的名字,不能在模板内部重用
5> 模板形参的名字能在不同模板中重用
6> 在同一个模板的声明和定义中,模板形参的名字不必相同。
7> 每一个模板的类型形参前面必须带上关键字class 或typename,在每一个非类型形参前面必须带上类型名字
5、模板形参关键字
1> 在函数模板形参表中,关键字typename 和class 具有相同的含义,可以相互换用。
非类型模板形参
1、在调用模板函数的时候,非类型形参将用值代替,值的类型在模板形参表中指定
template
void array_init(T (&parm) [N]) //参数是一个数组的引用。
{
for(size_t = 0;i != N ;++i)
{
parm[i];
}
}
int x[42];
array_init(x);
模板非类型形参是模板定义的内部常量值,在需要常量表达式的时候,尅使用费类型形参。
2、模板函数返回值
template
T1 sum(T2,T3);
long val3 = sum(i,log);
模板的编译
1、当编译器看到模板定义的时候它不立即产生代码,只有在看到使用模板类定义对象,或者用模板函数时。
2、要进行实例化,编译器必须能够访问定义模板的源代码。
3、编译器的“包含模型”和编译器的分别编译模型
4、类模板成员函数,类外定义。
5、非类型形参的模板实参
template
class Screen
{
screen():screen(hi*wid){}
}
Screen<14,12> a;
6、模板中的友员声明
7、成员模板;
1> 任意类(模板或者非模板),可以拥有本身为类模板,或函数模板的成员,这种模板称为成员模板,成员模板不能为虚。
8、类模板的static 成员
9、类模板的特化
10、类模板的部分特化
容器
容器:(1) 标准容器: 1> 顺序容器(vector、list、deque)
2> 关联容器(set、multset,map、multmap)
(2) iterator : 在容器内部定义的类型,模仿指针把容器当做数组来使用
(3)特殊容器:stack ,queue,priority_queue,悠闲队列 。没有区间构造函数,没有迭代器。
容器特性;
1> 在容器中中添加元素时,系统是将元素的值复制到容器里,容器内元素值的变化时,被复制的原值不会受影响。
1、STL :标准库定义了许多容器类以及一系列泛型算法
2、关联容器中的元素不是顺序(插入的)排列,而是按键(key)排序的。
3、顺序容器的元素排列次序与元素值无关,而是由元素添加到容器里的次序决定的。
vector 、list 、deque、string
关联容器
1、关联容器通过键(key)存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素。关联容器支持通过键来搞笑的查询和读取元素。
2、map 的元素以键-值(key-value)对的形式组织,键用作元素在map中索引而值则表示所存储和读取的数据。set 仅包含一个键,并有效地支持关于这个键时候存在的查询。
map和set 一个键对应一个元素,若一个键对应多个元素则用,multimap 和multiset
4、数据结构有:链表(list)、栈(stack)、队列(queue)、树、二叉树、二叉查找树
1> list:一个数据序列,用链表方式存储。对空间连续性没有要求,插入和删除数据方便,查找较
为慢。有单向链表、双向链表、环形链表。
2> stack :后进先出。插入和删除都只允许在序列的同一段进行
3> queue:先进先出。插入和删除在队列的不同端进行。
4> tree:一棵树可以是空树,否则就是由一个跟节点和若干颗互不交叉的子树构成。每一颗子树也是树。