1模板的概念
作用:建立通用的模具,大大提高复用性
2函数模板
C++另一种编程思想称为泛型编程,主要利用的技术就是模板
C++提供两种模板机制:函数模板和类模板
2.1函数模板语法
函数模板作用:
函数模板作用:
建立一个通用函数,其函数返回值类型和形参类型可以不具体指定,用一个虚拟的类型来带代表。
Template<typename T>\
函数声明多定义
Template--声明创建模板
Typename—其后面是一种数据类型,可以用class代替
T—通用的数据类型,名称可以替换,通常为大写字母
#include<iostream>
#include<string>
using namespace std;
template <typename T>
void myswap( T&a, T&b)
{
T temp = a;
a = b;
b = temp;
}
void test01()
{
int a = 10;
int b = 20;
double c = 10.1;
double d = 10.2;
//1.自动类型推导
myswap(a, b);
cout << "a=" << a<<endl;
cout << "b=" << b << endl;
myswap(c, d);
cout << "c=" << c << endl;
cout << "d=" << d << endl;
//2.自定义数据类型
myswap<int>(a, b);
myswap(a, b);
cout << "a=" << a << endl;
cout << "b=" << b << endl;
myswap(c, d);
cout << "c=" << c << endl;
cout << "d=" << d << endl;
}
int main()
{
test01();
return 0;
}
2.2函数模板注意事项
(1)自动类型推导,必须推导出一致的数据类型T,才可以使用。
(2)模板必须要确定出T的数据类型,才可以使用。
#include<iostream>
#include<string>
using namespace std;
//模板注意事项
template <typename T>
void myswap( T&a, T&b)
{
T temp = a;
a = b;
b = temp;
}
template <typename T>
void myswap1()
{
T temp = a;
a = b;
b = temp;
}
void test01()
{
int a = 10;
int b = 20;
double c = 10.1;
double d = 10.2;
//1.自动类型推导,必须有一致的数据类型
//myswap(a, c);
cout << "a=" << a<<endl;
cout << "b=" << b << endl;
//模板必须要确定出T的数据类型,才可以使用
myswap1<int>();
}
int main()
{
test01();
return 0;
}
2.3普通函数与函数模板的区别
(1)普通函数调用时可以发生自动类型转换(隐式类型转换)
(2)函数模板调用时,如果利用自动类型推导,不会发生隐式类型转换
(3)如果利用显示指定类型的方式,可以发生隐式类型
2.4普通函数与模板函数
1如果函数模板和普通函数都可以实现优先调用普通函数。
2.可以通过空模板参数列表来强制调用函数模板。
3.函数模板也可以发生重载。
4如果函数模板可以产生个更好的匹配优先调用函数模板。
2.5函数模板的局限性
1.模板并不是万能的,有些特定的数据类型,需要具体化方式做特殊实现
2.利用具体化模板,可以解决自定义类型的通用化
3.学习模板并不是为了写模板而是在STL能够运用系统提供的模板
3类模板
3.1类模板与函数模板的区别:
1.类模板没有自动类型推导的使用方式
2.类模板在模板参数列表中可以有默认参数
3.2类模板中成员函数创建时机
类模板中成员函数和普通函数中成员函数创建时机是有区别的:
普通类中的成员函数一开始就可以创建
类模板中的成员函数在调用时才创建
3.3类模板对象做函数参数:
类模板实例化出的对象,向函数传方式
一共有三种传递方式
1指定传入的类型—直接显示对象的数据类型
2参数模板化 –-将对象中参数变为模板进行传递
3整个类模板化 –将这个对象类型模板化进行传递
3.4类模板与继承
当类模板碰到继承时,需要注意以下几点:
1当子类继承的父类时一个类模板时,子类在声明的时候,需指定父类中T的类型。
2如果不指定,编译器无法给子类分配内存。
3如果想灵活指定出父类中T的类型,子类也需变为类模板
3.5类模板成员函数类外实现
3.6类模板分文件编写
解决方式1:直接包含.cpp文件
解决方式2:将声明和实现写道同一个文件夹中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制。
3.7模板配合友元函数的类内和类外实现
1全局函数类内实现;直接在类内声明友元即可
2全局函数需要提前让编译器知道全局函数的存在
建议:不要类外实现,直接做类内实现编译器可以识别
3.8类模板案例
实现一个数组类
- 可以对内置数据类型以及自定义数据类型进行存储
- 将数组中的数据存到堆区
- 构造函数可以传入数组的容量
- 提供对应的拷贝构造函数以及operator=防止浅拷贝问题
- 提供尾插法和尾删法对数组中的数据进行增加和删除
- 可以通过下标的方式访问数组中的元素
- 可以获取数组中当前元素的个数和数组的容量