第十六课(模板)
1,模板和泛型
泛型编程是指独立与任何类型的方式编写代码;泛型编程和面向对象编程,都依赖与某种形式的多态.面向对象编程的多态性在运行时应用于存在继承关系的类.一段代码可以忽略基类和派生类之间的差异.在泛型编程中,编写的代码可以用作多种类型的对象.面向对象编程所依赖的多态性称为运行时多态性,泛型编程所依赖的多态性称为编译时多态性或参数式多态性;
模板是泛型编程的基础,模板是创建类或者函数的公式;
模板是一种对类型进行参数化的工具,有两种形式:函数模板和类模板;
2,函数模板
针对仅参数类型不同的函数;
3,类模板
针对仅数据成员和成员函数类型不同的类;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uO7OnoDy-1616052576723)(C:\Users\daili\Desktop\CSDN笔记\相关图片\模板图例.png)]
4,函数模板
例子:
//实现两个对象的求和
//特点:功能相同,只有参数类型不同--将类型参数化
template<typename Type,typename Type2>
//定义模板参数列表
Type add(Type a, Type2 b)
{
return a + b;
}
5,函数模板调用
`显示类型调用: 需要在函数调用处的函数名后面加上类型参数;
如: fun(2,6);
`自动类型推导: 根据参数的类型进行推导,但是两个参数的类型必须一致,否则会报错;
如: fun(2,3);
注意:当需要两个及以上的参数,可以多些几个模板类型;
例子:
template <typename A,typename B>
auto fun(A a,B b)
{
}
6,函数模板和普通函数
1,当函数模板和普通函数参数都符合时,优先选择普通函数;
2,若想显示使用模板函数,则在函数名后加上<>类型列表;
3,如果函数模板产生更好的匹配,则使用函数模板;
注意:模板的声明与定义只能放在头文件中,对于函数模板声明和定义,文件会有一个新的名字-即hpp文件;
7,类模板
类模板与函数模板的定义和使用类似.当有两个或多个类功能相同,仅数据类型不同,就需要模板类;
案例://模板的参数类型定义写在类定义之前,在类里面任何位置都可使用;
template<typename T>
class V
{
public:
V(T a):_a(a){}
private:
T _a;
}
`类模板用于实现类所需数据的类型参数化;
`类模板在表示如数组,表,图等数据结构十分重要,这些数据结构的表示和算法不受所包含的元素类型的影响(STL);
8,继承中的类模板–类模板派生普通类
子类被模板类继承时,需要写父类的数据类型(数据类型的本质:如何分配内存空间);
案例:
template<typename H>
class A
{
public:
A(H h):v(h){}
void a()
{
cout<<v<<endl;
}
protected:
H v;
};
class B:public A<int>//指定具体类型
{
public:
using A<int>::A;
};
9,类模板–派生模板类
案例:
template<typename H>
class A
{
public:
A(H h):v(h){}
void a()
{
cout<<v<<endl;
}
protected:
H v;
};
template<typename N>
class B:public A<N>//指定具体类型
{
public:
using A<int>::A;
};
注意:子类在使用父类中的成员时,会提示找不到标识符:
解决方法:
1,通过this指针访问:this->父类成员;
2,通过父类访问:父类名<数据类型>::父类成员;
10,模板特化
模板函数的参数只能传入类类型的参数;特化函数的参数只能传入对应的参数类型;
案例:
//模板函数
template<typename T>
int compare(T a,T b)
{
return a==b?0:(a>b?1,-1);
}
模板函数支持int...等类型的计算,但不能用来比较字符串(char*),因为这个函数比较的是串指针,而不是字符串本身;
//特化函数
template<>//必须写,否则成了重载函数
int compare(const char* a,const char* b)
{
return strcmp(str1,str2);//可以比较字符串了;
}
11,array类
C++中提供了一个静态数组类:头文件;
例子:
array<int,99> _ad{0};
自己实现这个类:
template<typename Type,size_t t>
class Array
{
public:
Type& operator[](int i)
{
return _array[i];
}
private:
Type _array[t];//[]里面只能放常量
};
必须知道的类型别名:
size_t :unsigned int
DWORD :unsigned long
WORLD :unsigned short
12,using其他用法
using和typedef有类似的作用,而且能够完全替代typedef;
案例:
typedef int INT;
using INT = int;
typedef void (*pFun)();
using Pfun =void(*)();
template<typename T>
typedef Array<T,9> arr;//error
template<typename T>
using arr=Array<T,9>;//true