C++模板

函数模板

eg.

编译器自动推演帮你生成需要的函数或类

单模板参数问题

但是,当前模板只能支持相同类型参数运算

eg.

解决方法:

1.

将某一类型强制类型转化为另一类型

2.

取消推演过程,直接给类型

3.

auto自动推演返回值,template 2个类型

有多个模板参数,也可以多个模板参数显式实例化

模板参数类型问题

正常函数模板类型可以根据传入参数的类型推出模板的类型

但在特殊情况下(参数中没有模板参数),无法推导出模板参数的类型

因此需要显式实例化

普通函数和函数模板可以同时存在,编译器会自己选择最匹配的函数

类模板

类模板的存在可以让一个栈(或者队列等容器)中存储多种类型的数据

eg.

这样就能让一个栈同时存两种类型的数据

声明定义分离:

非类型模板参数

如果实现不同的大小的栈来存放不同大小的数据

可以使用非类型模板参数来限定他的大小

eg.

这样编译器会根据传入的参数自动生成相应大小的栈

减少了代码重复度

C++14规定一般的非类型模板参数只能定义整形

但是C++20可以定义其他内置类型的非类型模板参数

但是自定义类型不可以作为非类型模板参数

非类型模板参数是一个常量(右值),不能修改

非类型模板参数可以给缺省值

非类型模板参数的应用

固定大小的数组

与c语言中的一般数组的区别

c语言的数组对越界的检查是一种抽查行为,

是设置标志位抽查(标志位就是在数组向两端额外标志几个位置用于检查)

是看标志位的值有没有被修改(越界读无法被检查)

但是C++中的array对于数组越界的检查非常严格(不管读还是写)

但是array的实际应用场景较少,基本都可以用vector替代

弊端

array的空间是开在函数栈帧里的,但是栈帧空间较小

因此array比较鸡肋

typename

类模板没实例化时不去里面查细节的语法

vector<T>是一个类模板,没有进行实例化(只有使用才能实例化)

vector<T>::const_iterator 是从类模板中取一个东西(取出其中的const_iterator)

但是编译器不会取出它

因为没有对语法进行详细的检查,编译器不敢取

而且指定了类域来取(指定了vector<T>的类域),取出的东西可能是typedef或者是内部类(都是类型),

但是也可能是静态变量

可能是静态变量,也可能是类型

类模板没实例化时,不能取查细节语法

因此无法确认取静态变量还是类型

因此要加typename

但是,下面这个函数不需要加typename,因为vector<int>已经实例化了,是一个已经实例化的类

编译器就可以确认了

当然,可以使用auto来避免这种问题

eg.

模板的特化

对于指针等情况,需要特殊处理,可以使用模板的特化

特化的目的就是对特殊的类型进行特殊的处理

函数模板的特化

eg.

但是,函数模板的特化的使用较为容易出错

需要注意const修饰的对象

eg.

而且,模板和函数是可以同时存在的(可以构成重载)

因此可以直接写一个重载函数

尽量避免使用函数模板的特化

类模板的特化

eg.

注意,与函数不同,由于不存在类重载,因此只能使用类模板的特化

偏特化

特化部分参数

eg.

在上面的例子里,只要第二个参数是int,就会走特化版本的类

限定模板的类型

eg.

在上面的例子里,如果参数是指针,就会走特化的类 

限定模板类型也可以限定引用

eg.

模板的声明和定义分离

模板不支持分离编译

调用函数时会转换成call这个函数的地址

在只包含xxx.h文件时,普通函数可以链接找到函数地址,但是函数模板链接不能找到函数地址

因为模板不会被编译器实例化,就没有地址放进符号表,所以链接找不到

显式实例化

为了使用声明和定义分离,可以采取显式实例化

但是一般情况下不会使用

因为显式实例化具有其局限性

显式实例化并不方便,因为模板的使用可能很多,需要不断的增加显示实例化

因此最好在使用模板时,不要进行声明和定义的分离

对于一个类,可以将短的成员函数直接放到类里面

长的就放到外面

但是始终都放在一个文件里面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值