C++笔记 模板的进阶知识

news2024/11/15 8:22:06

目录

1. 非类型模板参数

2.模板的特化

2.1 函数模板的特化

 2.2 类模板的特化

2.2.1 全特化

 2.2.2 偏特化

3.模板的分离编译

3.1 什么是分离编译?

3.2 模板的分离编译

4.模板的总结


模板的初阶内容:(594条消息) C++模板的原理和使用_全貌的博客-CSDN博客_c++模板实现原理https://blog.csdn.net/qq_64105689/article/details/126693075?spm=1001.2014.3001.5501

1. 非类型模板参数

模板的参数分为 类类型形参和非类型形参

类类型形参:出现在模板参数列表中,由class 和 typename关键字修饰

非类型形参:用一个常量来做类(函数)模板的参数,在类(函数)中可将该参数当作常量使用

namespace test
{
    //实现一个包含非类型模板参数的静态数组
	template<class T, size_t N = 10>//在类中,可以将N当作常量使用
	class array
	{
	public:
		T& operator[](size_t i)
		{
			return _arr[i];
		}
		const T& operator[](size_t i)
		{
			return _arr[i];
		}
		bool empty()
		{
			//...
		}
	private:
		K _arr[N];
		size_t size;
	};
}

字符串、浮点数、类对象是不允许作为非类型模板参数

非类型模板参数必须在编译时就确定结果

2.模板的特化

使用模板可以编写一些与类型无关的代码,但在面对特殊类型结果就会错误

比如实现了一个比较函数Less,大部分情况下比较的结果都是正确的,但是对指针类型,比较的是指针存放地址的大小,结果显然易见是错误的,这时候模板的特化很好的解决了这样的问题

template<class T>
bool Less(const T& a, const T& b)
{
	return a < b;
}
int main()
{

	int a1 = 7;
	int a2 = 6;
	cout << Less(a1, a2) << endl;//比较的是a1和a2的值
                                 //结果正确

	int* ptr1 = &a1;
	int* ptr2 = &a2;
	cout << Less(ptr1, ptr2) << endl;//比较的是a1和a2的地址
                                     //应返回false,打印0,结果错误
	return 0;
}

2.1 函数模板的特化

1.必须先有一个函数模板

template<class T>//要特化的函数模板
void Func(T& left, T& right)
{
};

2.template后面跟空的<>

template<>//跟一对空的<>
void Func<int*>(int* val1,int* val2)
{
    
}

3.函数名后跟一对尖括号,括号内是要特化的类型

template<>//跟一对空的<>
void Func<int*>(int* val1,int* val2)//函数名Func后跟要特化的类型
{
    
}

4.形参列表必须跟模板参数完全相同,不然就会出现一些奇怪的错误

template<>//跟一对空的<>
void Func<int*>(int* val1,int* val2)//函数名Func后跟要特化的类型
{
                                    //新参列表的类型要与特化的类型int*一致        
}

 当然函数模板是不建议使用特化的,因为遇到一些复杂的类型函数模板不好处理时,可以直接显示写出该函数。

bool Func(int* left,int* right)
{
    return *left < *right;
}

 2.2 类模板的特化

2.2.1 全特化

顾名思义,就是将函数模板参数全部确定化

template<class T1, class T2>
class Func
{
public: 
    Func(){cout << "Func() T1,T2" << endl;}
private:
    T1 _a1;
    T2 _a2;
};


template<>
class Func<char, int>
{
public: 
 Func(){cout << "Func char, int" << endl;}
private:
    char _a1;
    int _a2;
};

int main()
{
    Func<int,int> f1;
    Func<char,int> f2;
    return 0;
}

 2.2.2 偏特化

针对任意模板参数进行特殊处理

偏特化分为两种:

1.部分特化

就是特化模板参数的部分,其他跟全特化一致        

2.对参数更进一步的限制

 比如模板参数为T1,T2,那么可以特化为<T1*, T2*>、<T1&,T2&>的版本

template<class T1, class T2>
class Func
{
public: 
    Func(){cout << "Func() T1,T2" << endl;}
private:
    T1 _a1;
    T2 _a2;
};
template<>
class Func<T1*, T2*>
{
public: 
    Func(){cout << "Func() T1*,T2*" << endl;}
private:
    T1* _a1;
    T2* _a2;
};
template<>
class Func<T1&, T2&>
{
public: 
    Func(){cout << "Func() T1&,T2&" << endl;}
private:
    T1& _a1;
    T2& _a2;
};

3.模板的分离编译

3.1 什么是分离编译?

一个程序(项目) 由若干个源文件共同实现,通过编译形成目标文件,最后将目标文件链接形成单一的可执行文件,执行的过程就叫做分离编译。

3.2 模板的分离编译

举个例子:

//a.h
template<class T>
T& Add(const T& letf, const T& right);

//a.cpp
template<class T>
T& Add(const T& letf, const T& right);
{
    return left + right;
}

//test.cpp
#include"a.h"
int main()
{
    Add(1,2);
}

C/C++程序要运行,要经过 预处理 -> 编译 -> 汇编 -> 链接

编译:对程序按照语言特性进行词法、语法、语义分析,错误检查无误后生成汇编代码

头文件不参加编译,编译器对程序内多个源文件是单独分开独立编译的。

链接,将多个.obj文件链接到一起,并处理没有解决的地址问题

解决方法:将.h跟.cpp文件放入一个文件xxx.hpp或xxx.h里面 

4.模板的总结

优点:

1.模板复用了代码,增加了开发效率,C++的模板库(STL)也因此而诞生

 2.增强了代码的灵活性

缺点:

1.模板会导致代码膨胀的问题,编译时间变长

2.模板编译错误时,错误信息非常凌乱,不易定位错误

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/356749.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【干货】如何打造HR无法拒绝的简历?测试开发大牛带手把手你写简历!

通过率90%&#xff0c;优秀的软件测试简历长什么样&#xff1f; 也许口才好的人会觉得简历不重要&#xff0c;能说就行了&#xff0c;那是因为你没有体会过石沉大海的感觉&#xff01; 很多人觉得疑惑&#xff0c;为什么我投了那么多简历&#xff0c;都没有接到面试通知&…

加油站会员管理小程序实战开发教程15 完结篇

这篇是本次实战课程的最后一篇,我们在上篇还有两个问题没解决。一个是会员卡类型显示不对,一个是不同的会员卡我们希望背景色显示不同。我们先处理一下这两个问题 1 显示会员卡类型 在列表上直接显示会员卡类型,目前显示的是数字,这个是因为枚举类型导致的。枚举类型在数…

关于vb6无边框的窗体开发遇到的部分问题的解决方案

为了美化或自定义窗体&#xff0c;通常会把窗体做成无边框形式&#xff0c;使用无边框窗体会存在一些问题的&#xff0c;以vb为例&#xff0c;当窗体borderstyle设置为0时&#xff0c;会出现以下问题:1.任务栏不再出现程序图标 2.窗体无法拖行移动 3.窗体无法拖动缩放&#…

WampServer安装教程

文章目录简介&#xff1a;官网地址安装步骤&#xff1a;我是阿波&#xff0c;学习PHP记录一下笔记&#xff0c;如果对你有帮助&#xff0c;欢迎一键三连&#xff0c;谢谢&#xff01; 简介&#xff1a; WampServer是一个用于Windows操作系统的Web开发环境&#xff0c;其名称来…

10- 天猫用户复购预测 (机器学习集成算法) (项目十) *

项目难点 merchant: 商人重命名列名: user_log.rename(columns{seller_id:merchant_id}, inplaceTrue)数据类型转换: user_log[item_id] user_log[item_id].astype(int32)主要使用方法: xgboost, lightbm竞赛地址: 天猫复购预测之挑战Baseline_学习赛_天池大赛-阿里云天池…

java并发编程原理1(原子性,可见行,有序性,volatile,synchronized)

一、原子性&#xff1a; 1.1 Java中如何实现线程安全? 多线程操作共享数据出现的问题。 锁&#xff1a; 悲观锁&#xff1a;synchronized&#xff0c;lock乐观锁&#xff1a;CAS 可以根据业务情况&#xff0c;选择ThreadLocal&#xff0c;让每个线程玩自己的数据。 1.2 C…

内大-oj练习题(2期)

内大oj2期 1. 输出一个数的质数因子2. 寻找完数3. 圆的面积4. 求同存异5. 2的k进制数6. 输出排序序列6. DNA算法1. 输出一个数的质数因子 介绍 因子,例如 33=9 (3就是因子); 19=9(1,9就是因子) 质数, 只能被1和本身整除的数 题目 代码 #include <iostream>

Windows7下使用VMware11.1.1安装ubuntu-16.04.7

一、说明二、安装说明三、安装步骤详解1、先安装VMware软件2、创建虚拟机3、编辑虚拟机4、开启虚拟机&#xff0c;初始化Linux系统一、说明 虽然VMware和ubuntu最新版已经很高了&#xff0c;我这电脑由于是win7配值还低&#xff0c;所以采用低版本来安装 VMware版本&#xff1…

C++Primer15.5节练习

练习15.18&#xff1a; Base* p &d1&#xff1a;合法 p &d2&#xff1a;不合法&#xff0c;只有当派生类公有地继承基类时&#xff0c;用户代码才能使用派生类向基类的转换 p &d3&#xff1a;不合法&#xff0c;只有当派生类公有地继承基类时&#xff0…

ChatGpt与Google 谁能给出最好的回答

ChatGPT由于其先进的会话和技术功能而越来越受欢迎。你可以问聊天机器人任何你想问的问题&#xff0c;它会在几秒钟内输出答案。虽然它不是一个搜索引擎&#xff0c;你应该使用ChatGPT作为你的信息来源而不是谷歌&#xff0c;百度吗? 我们来根据国外的一场测试来看一下 ChatG…

spring注解方式整合Dubbo

系列文章目录 文章目录系列文章目录一、创建一个父工程项目二、创建子模块(dubbo-api模块)二、创建子模块(dubbo-provider模块)三、创建子模块(dubbo-consumer模块)总结一、创建一个父工程项目 这里我们通过Spring Initializer 来帮我们构建一个spring-dubbo这个父项目,点击nex…

python进阶--Numyp库(一)

一、Numpy库介绍 NumPy&#xff08;Numerical Python&#xff09;是Python的⼀种开源的数值计算扩展。提供多维数组对象&#xff0c;各种派⽣对象&#xff08;如掩码数组和矩阵&#xff09;&#xff0c;这种⼯具可⽤来存储和处理⼤型矩阵&#xff0c;⽐Python⾃身的嵌套列表&am…

【Redis 高级】- 持久化 - RDB

【Redis 高级】- 持久化 - RDB &#x1f451;什么是持久化呢&#xff1f; 那当然是够持久呀&#xff0c;这个持久如果在你不主动去删除的情况下&#xff0c;它就一直存在的。 &#x1f3b7;那么这有什么用呢&#xff1f; 举个栗子&#xff1a;我们在用 PowerPoint 在写价值 …

WEB系列(二)-----------XSS

XSS原理及基础 定义 恶意攻击者会往Web页面里插入JS代码,当用户点击网页时.镶嵌的JS代码就会执行,从而达到恶意的特殊目的. 原因 程序对输入和输出的控制不够严格&#xff0c;导致payload输出到前段时被浏览器当做有效代码执行从而产生危害。 分类 存储型反射型DOM型 测…

常见排序算法--Java实现

常见排序算法--Java实现插入排序直接插入排序折半插入排序希尔排序交换排序冒泡排序快速排序选择排序直接选择排序堆排序归并排序基数排序各种排序方法比较在网上找了些排序算法的资料。此篇笔记本人总结比较&#xff0c;简单注释&#xff0c;觉得比较好理解&#xff0c;且相对…

四大步骤,教你彻底关闭Win10自动更新

文章目录一、禁用Windows Update服务二、在组策略里关闭Win10自动更新相关服务三、禁用任务计划里边的Win10自动更新四、在注册表中关闭Win10自动更新参考资料一、禁用Windows Update服务 1、同时按下键盘 Win R&#xff0c;打开运行对话框&#xff0c;然后输入命令 services…

C语言运算符优先级和结合性一览表

所谓优先级就是当一个表达式中有多个运算符时&#xff0c;先计算谁&#xff0c;后计算谁。 运算符的优先级从高到低大致是&#xff1a;单目运算符、算术运算符、关系运算符、逻辑运算符、条件运算符、赋值运算符()和逗号运算符 简单记就是&#xff1a;&#xff01; > 算术运…

一起学 pixijs(1):常见图形的绘制

大家好&#xff0c;我是前端西瓜哥。 pixijs 是一个强大的 Web Canvas 2D 库&#xff0c;以其强大性能而著称。其底层使用了 WebGL 实现了硬件加速&#xff0c;当然如果不支持的话&#xff0c;也能回退为 Canvas。 本文使用的 pixijs 版本为 7.1.2。 Application Applicati…

【LeetCode】剑指 Offer 08. 二叉树的下一个节点 p65 -- Java Version

题目链接&#xff1a;无题目链接&#xff0c;不知道为啥力扣上找不到这一题。 1. 题目介绍&#xff08;08. 二叉树的下一个节点&#xff09; 题目&#xff1a;给定一个二叉树和其中的一个节点&#xff0c;请找出中序遍历顺序的下一个节点并且返回。注意&#xff0c;树中的节点…

linux线程阻塞中CPU的占用率

linux线程阻塞中CPU的占用率 一、简介 总所周知Linux系统下&#xff0c;我们编写的程序进入阻塞后&#xff0c;系统把任务挂起&#xff0c;交给内核进行处理&#xff0c;此时我们的进程CPU占用率不高&#xff0c;可以说是占用率0.0%&#xff0c;让CPU资源交给其他进程处理&am…