目录
一,模板初阶
1.泛型编程
2.函数模板
2.1 函数模板概念
2.2 函数模板格式
2.3 函数模板的原理
2.4 函数模板的实例化
2.5 模板参数的匹配原则
3.类模板(模板类,模板函数)
3.1 类模板定义格式
二,STL简介
1. 什么是STL
2. STL的版本
2.1 原始版本
2.2 P.J.版本
2.3 RW版本
2.4 SGI版本
3.STL的六大组件
一,模板初阶
1.泛型编程
编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。
void Swap(int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
void Swap(double& left, double& right)
{
double temp = left;
left = right;
right = temp;
}
void Swap(char& left, char& right)
{
char temp = left;
left = right;
right = temp;
}
使用函数重载虽然可以实现,但是有一下几个不好的地方:
1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增
加对应的函数。
2. 代码的可维护性比较低,一个出错可能所有的重载均出错 。
那能否告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码呢?
2.函数模板
2.1 函数模板概念
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
2.2 函数模板格式
template<typename T1, typenameT2,......,typenameTn>
返回值类型 函数名(参数列表){}
例子:
template <class T>
void Swap(const T& x,const T& y)
{
T temp = x;
x = y;
y = temp;
}
typename是用来定义模板参数关键字,也可以使用class。
参数问题
当时只有一个class时,两个参数必须是同一类型。
template <class T>
void Swap(const T& x,const T& y)
{
T temp = x;
x = y;
y = temp;
}
int main()
{
int x1 = 1;
int x2 = 2;
double y1 = 3.0;
double y2 = 4.0;
Swap(x1, x2);//对
Swap(y1, y2);//对
Swap(x1, y1);//错
}
如果想要交换两个不同类型就要写两个class
template <class T1,class T2>
void Swap(const T1& x,const T2& y)
{
T1 temp = x;
x = y;
y = temp;
}
int main()
{
int x1 = 1;
int x2 = 2;
double y1 = 3.0;
double y2 = 4.0;
Swap(x1, y1);
cout << x1 << ' ' << y1 << endl;
}
2.3 函数模板的原理
函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。
所以其实模板就是将本来应该我们做的重复的事情交给了编译器。
2.4 函数模板的实例化
用函数模板生成对应的函数,称为函数模板的实例化。模板参数实例化分为:隐式实例化
和显式实例化。
(1). 隐式实例化:让编译器根据实参推演模板参数的实际类型
template <class T>
int Add(const T& x,const T& y)
{
return x + y;
}
int main()
{
int x1 = 1;
int x2 = 2;
double y1 = 3.0;
double y2 = 4.0;
// 此时有两种处理方式:1. 用户自己来强制转化 2. 使用显式实例化
Add(x1, (int)y1);
cout << x1 << ' ' << y1 << endl;
}
(2).显式实例化
在函数名后的<>中指定模板参数的实际类型
template <class T>
int Add(const T& x,const T& y)
{
return x + y;
}
int main()
{
int x1 = 1;
int x2 = 2;
double y1 = 3.0;
double y2 = 4.0;
cout << Add<double>(x1, y1) << endl;
}
2.5 模板参数的匹配原则
(1). 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这
个非模板函数。
template <class T>
int Add(const T& x,const T& y)
{
return x + y;
}
int Add(int a, int b)
{
cout << "ADD: ";
return (a + b);
}
int main()
{
int x1 = 1;
int x2 = 2;
double y1 = 3.0;
double y2 = 4.0;
cout << Add(x1, y1) << endl;
}
运行结果:
(2). 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板。
int Add(int left, int right)
{
cout << "Add1:";
return left + right;
}
template<class T1, class T2>
T1 Add(T1 left, T2 right)
{
cout << "Add2:";
return left + right;
}
void main()
{
cout << Add(1, 2) << endl; // 与非函数模板类型完全匹配,不需要函数模板实例化
cout << Add(1, 2.0) << endl; // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的
}
运行结果:
3.类模板(模板类,模板函数)
3.1 类模板定义格式
template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};
例如:
类模板实现栈
#include<iostream>
using namespace std;
template<typename T>
class Stack
{
public:
Stack(int n = 4)
:_array(new T[n])
, _capacity(n)
, _size(0)
{}
~Stack()
{
delete[] _array;
_array = nullptr;
_size = _capacity = 0;
}
void Push(const T& data)
{
if (_size == _capacity)
{
T temp = new T[_capacity * 2];
memcpy(temp, _array, sizeof(T) * _size);
_array = temp;
_capacity = _capacity * 2;
}
_array[_size++] = data;
}
private:
T* _array;
size_t _capacity;
size_t _size;
};
int main()
{
Stack<int> st1;
Stack<double> st2;
return 0;
}
当声明与定义分离时,要声明模板类
template<typename T>
class Stack
{
public:
Stack(int n = 4)
:_array(new T[n])
, _capacity(n)
, _size(0)
{}
~Stack()
{
delete[] _array;
_array = nullptr;
_size = _capacity = 0;
}
void Push(const T& data);
private:
T* _array;
size_t _capacity;
size_t _size;
};
template<typename T>
void Stack<T>::Push(const T& data)
{
if (_size == _capacity)
{
T temp = new T[_capacity * 2];
memcpy(temp, _array, sizeof(T) * _size);
_array = temp;
_capacity = _capacity * 2;
}
_array[_size++] = data;
}
二,STL简介
1. 什么是STL
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包含数据结构与算法的软件框架。
2. STL的版本
2.1 原始版本
Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。 HP 版本--所有STL实现版本的始祖。
2.2 P.J.版本
由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用,不能公开或修改,缺陷:可读性比较低,符号命名比较怪异。
2.3 RW版本
由Rouge Wage公司开发,继承自HP版本,被C+ + Builder 采用,不能公开或修改,可读性一般。
2.4 SGI版本
由Silicon Graphics Computer Systems,Inc公司开发,继承自HP版 本。被GCC(Linux)采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。我们学习STL主要参考的就是这个版本。
3.STL的六大组件
本篇完