C++的泛型编程
简介:
- 概念:编写不依赖具体数据类型的程序;
- 目的:将程序尽可能的通用;将算法从数据结构中抽象出来,成为通用算法;
- 应用:C++中模板为泛型程序设计提供了基础;STL(标准模板库)是泛型程序设计的例子;
模板:
- 概念:模板是一种用不确定类型参数来产生一系列函数和类的机制;通过模板我们可以产生类和函数的集合,使他们操作不同的数据类型,从而避免为每一种数据类型单独产生一个函数和类;
- 分类:函数模板;类模板;
- 模板只是说明,需要实例化之后才能执行和使用;
函数模板
- 定义:函数模板使用和普通函数一样,但它的类型可以通过参数来传递,在函数定义时可以不指明具体的数据类型;当发送函数调用时,编译器可根据传入的实参自动推断数据类型;
- 语法:
template <模板参数表>
<返回值类型> <函数名> (<参数表>)
{
<函数体>
}
template <typename T>
void myswap(T &a,T &b)
{
T tmp;
tmp = a;
a = b;
b = tmp;
}
- template是函数模板定义关键字;<模板参数表>:用来定义函数参数的类型,参数类型有一个或多个,用逗号隔开,不能为空;模板参数常用形式:class/typename;
- 函数模板优点:代码复用,适合所有类型。克服普通函数弊端;编译器会进行类型检查。克服宏定义弊端。缺点:调试比较难;一般编写一个类型确定的函数,运行通过后再修改成函数模板;
- 调试方式:推荐使用具体类型显示调用
Swap<int>(a,b);; - 原理分析:函数模板中声明了参数类型T,表示了一种抽象类型;编译器检查到程序调用函数时,根据传递参数的实际类型生成模板函数;
类模板
- 定义:是对一批成员数据类型(成员函数和程序数据)不同的类的抽象;程序员只要为这一批类所组成的整个类家族创建一个类模板,给出一套程序代码,就可以生成多种具体的类;
- 语法:
template <<模板参数表>>
class <类模板名>
{
<成员函数与成员变量>
};
template <typename T>
class Sqlist
{
public:
Sqlist();
~Sqlist();
bool addData(T value);
private:
T *data;
int size;
};
template <<模板参数表>>
<返回值类型> <类模板名> <<模板参数名列表>>::<成员函数名>(<参数表>)
{
<函数体>
}
template <typename T>
bool Sqlist<T,size>::addData(T value)
{
cout << "插入数据" << endl;
return false;
}
类模板名<真实类型参数表> 对象名(构造函数实际参数表)
Sqlist<int> a(5);
- 原理:编译器由模板生成类的过程叫类模板的实例化;编译器自动用具体的数据类型替换类模板中的类型参数,生成模板类的代码;由类模板实例化得到的类叫做模板类;
- 二次编译机制:在编译器进行编译时,编译器会产生模板函数的声明,当实际确认类型后调用的时候,会根据调用的类型进行再次帮我们生成对应类型的函数生命和定义;二次编译机制在模板类中声明友元函数,且函数实现在类外的时候会因为编译器找不到友元函数的实现二报错;解决方案:类的前置声明;有缘模板函数的前置声明;友元模板函数声明需要增加泛型支持;
- 类模板与非类型参数:
非类型参数:用于说明类模板中的属性,待定的不再是某个类型,而是数值;template <typename T,int size>//size是非类型参数; Sqlist<int,5> a;//非类型参数直接在<>内传值
类型参数:用来说明类模板中的属性、成员操作的参数类型与返回值;
限制:只能是整数、枚举类型、指向外部链接的指针(指针指向的对象不能再指针所指的文件中定义,必须在别的文件中定义); - 示例:
#include <iostream>
using namespace std;
template <typename T,int size>
class Sqlist
{
public:
Sqlist();
~Sqlist();
bool addData(T value);
bool delData();
void show();
void clear();
private:
T *data;
int index;
};
template <typename T,int size>
Sqlist<T,size>::Sqlist() : data(new T[size]),
index(0)
{
}
template <typename T,int size>
Sqlist<T,size>::~Sqlist()
{
delete []data;
}
template <typename T,int size>
bool Sqlist<T,size>::addData(T value)
{
cout << "插入数据" << endl;
if (index < size)
{
data[index ++] = value;
cout << data[0] << endl;
return true;
}
cout << "列表已满" << endl;
return false;
}
template <typename T,int size>
bool Sqlist<T,size>::delData()
{
if (index > 0)
{
index--;
return true;
}
cout << "列表为空" << endl;
return false;
}
template <typename T,int size>
void Sqlist<T,size>::show()
{
int i = 0;
for (i = 0;i < index;i++)
{
cout << "data[" << i << "] = " << data[i] << endl;
}
}
template <typename T,int size>
void Sqlist<T,size>::clear()
{
index = 0;
}
int main(int argc, const char *argv[])
{
int i;
Sqlist<int,5> a;
a.addData(1);
a.addData(2);
a.addData(3);
a.show();
a.delData();
a.show();
return 0;
}