C++之类模板全特化和偏特化
类模板
类模板是通用类的描述,使用任意类型(泛型)来描述类的定义。
使用类模板的时候,指定具体的数据类型,让编译器生成该类型的类定义。
注意:函数模板中可以不指定具体数据类型,让编译器自动推到,但是类模板不可以。
注意:模板编程不支持分离式编译,即模板类/模板函数的声明与定义应该放在头文件里,否则会在链接时报错;
template <class T>
class 类模板名
{类的定义;
};
注意
1)在创建对象的时候,必须指明具体的数据类型。
2)使用类模板时,数据类型必须适应类模板中的代码。
3)类模板可以为通用数据类型指定缺省的数据类型(C++11标准的函数模板也可以)。
4)模板类的成员函数可以在类外实现。
5)可以用new创建模板类对象。
6)在程序中,模板类的成员函数使用了才会创建。
下面给出示例
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
template <class T1, class T2 = string>
class AA
{
public:T1 m_a; // 通用类型用于成员变量。T2 m_b; // 通用类型用于成员变量。AA() {} // 默认构造函数// 通用类型用于成员函数的参数。AA(T1 a, T2 b) :m_a(a), m_b(b) { }// 通用类型用于成员函数的返回值。T1 geta() // 获取成员m_a的值。{T1 a = 2; // 通用类型用于成员函数的代码中。return m_a + a;}T2 getb(); // 获取成员m_b的值。
};template <class T1, class T2>
T2 AA<T1, T2>::getb() // 获取成员m_b的值。
{return m_b;
}
int main()
{AA<int, string>* a = new AA<int, string>(3, "西施"); // 用模板类AA创建对象a。cout << "a->geta()=" << a->geta() << endl;cout << "a->getb()=" << a->getb() << endl;delete a;return 0;
}
类模板全特化和部分特化
模板类具体化(特化、特例化)有两种:完全具体化和部分具体化。
具体化程度高的类优先于具体化程度低的类,具体化的类优先于没有具体化的类。
具体化的模板类,成员函数类外实现的代码应该放在源文件中。
下面给出示例
#include <iostream>
using namespace std; // 类模板
template<class T1, class T2>
class AA {
public:T1 m_x;T2 m_y;AA(const T1 x, const T2 y) :m_x(x), m_y(y) { cout << "类模板:构造函数。\n"; }void show() const;
};
template<class T1, class T2>
void AA<T1, T2>::show() const
{cout << "类模板:x = " << m_x << ", y = " << m_y << endl;
}
// 类模板特化
template<>
class AA<int, string> {
public:int m_x;string m_y;AA(const int x, const string y) :m_x(x), m_y(y) { cout << "完全具体化:构造函数。\n"; }void show() const;
};void AA<int, string>::show() const
{cout << "完全具体化:x = " << m_x << ", y = " << m_y << endl;
}
// 类模板部分特化
template<class T1>
class AA<T1, string> {
public:T1 m_x;string m_y;AA(const T1 x, const string y) :m_x(x), m_y(y) { cout << "部分具体化:构造函数。\n"; }void show() const;
};
template<class T1>
void AA<T1, string>::show() const
{cout << "部分具体化:x = " << m_x << ", y = " << m_y << endl;
}
int main()
{// 具体化程度高的类优先于具体化程度低的类,具体化的类优先于没有具体化的类。AA<int, string> aa1(8, "张三"); // 将使用完全具体化的类。AA<char, string> aa2(8, "李四"); // 将使用部分具体化的类。AA<int, double> aa3(8, 9666); // 将使用模板类。
}
模板类于继承
1)模板类继承普通类(常见)。
2)普通类继承模板类的实例化版本。
3)普通类继承模板类。(常见)
4)模板类继承模板类。
5)模板类继承模板参数给出的基类(不能是模板类)。
下面主要讲普通类继承模板类
#include <iostream>
using namespace std; template<class T1, class T2>
class BB
{
public:T1 m_x;T2 m_y;BB(const T1 x, const T2 y) : m_x(x), m_y(y) { cout << "调用了BB的构造函数。\n"; }void func2() const { cout << "调用了func2()函数:x = " << m_x << ", y = " << m_y << endl; }
};template<class T1, class T2>
class AA:public BB<T1,T2> // 普通类AA变成了模板类,才能继承模板类。
{
public:int m_a;AA(int a, const T1 x, const T2 y) : BB<T1,T2>(x,y),m_a(a) { cout << "调用了AA的构造函数。\n"; }void func1() { cout << "调用了func1()函数:m_a=" << m_a << endl;; }
};int main()
{AA<int,string> aa(3,8, "我是一只傻傻鸟。");aa.func1();aa.func2();return 0;
}
模板类继承模板类
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。template<class T1, class T2>
class BB // 模板类BB。
{
public:T1 m_x;T2 m_y;BB(const T1 x, const T2 y) : m_x(x), m_y(y) { cout << "调用了BB的构造函数。\n"; }void func2() const { cout << "调用了func2()函数:x = " << m_x << ", y = " << m_y << endl; }
};template<class T1, class T2>
class AA:public BB<T1,T2> // 普通类AA变成了模板类,才能继承模板类。
{
public:int m_a;AA(int a, const T1 x, const T2 y) : BB<T1,T2>(x,y),m_a(a) { cout << "调用了AA的构造函数。\n"; }void func1() { cout << "调用了func1()函数:m_a=" << m_a << endl;; }
};template<class T, class T1, class T2>
class CC :public BB<T1, T2> // 模板类继承模板类。
{
public:T m_a;CC(const T a, const T1 x, const T2 y) : BB<T1, T2>(x, y), m_a(a) { cout << "调用了CC的构造函数。\n"; }void func3() { cout << "调用了func3()函数:m_a=" << m_a << endl;; }
};int main()
{CC<int,int,string> cc(3,8, "芜湖");cc.func3();cc.func2();
}
模板类继承模板参数给出的基类
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。class AA {
public:AA() { cout << "调用了AA的构造函数AA()。\n"; }AA(int a) { cout << "调用了AA的构造函数AA(int a)。\n"; }
};class BB {
public:BB() { cout << "调用了BB的构造函数BB()。\n"; }BB(int a) { cout << "调用了BB的构造函数BB(int a)。\n"; }
};class CC {
public:CC() { cout << "调用了CC的构造函数CC()。\n"; }CC(int a) { cout << "调用了CC的构造函数CC(int a)。\n"; }
};template<class T>
class DD {
public:DD() { cout << "调用了DD的构造函数DD()。\n"; }DD(int a) { cout << "调用了DD的构造函数DD(int a)。\n"; }
};template<class T>
class EE : public T { // 模板类继承模板参数给出的基类。
public:EE() :T() { cout << "调用了EE的构造函数EE()。\n"; }EE(int a) :T(a) { cout << "调用了EE的构造函数EE(int a)。\n"; }
};int main()
{EE<AA> ea1; // AA作为基类。EE<BB> eb1; // BB作为基类。EE<CC> ec1; // CC作为基类。EE<DD<int>> ed1; // DD<int>作为基类。// EE<DD> ed1; // DD作为基类,错误。
}
相关文章:
C++之类模板全特化和偏特化
类模板类模板是通用类的描述,使用任意类型(泛型)来描述类的定义。使用类模板的时候,指定具体的数据类型,让编译器生成该类型的类定义。注意:函数模板中可以不指定具体数据类型,让编译器自动推到…...

Python 手写数字识别 MNIST数据集下载失败
目录 一、MNIST数据集下载失败 1 失败的解决办法(经验教训): 2 亲测有效的解决方法: 一、MNIST数据集下载失败 场景复现:想要pytorchMINIST数据集来实现手写数字识别,首先就是进行MNIST数据集的下载&am…...
华为机试题:HJ61 放苹果(python)
文章目录博主精品专栏导航知识点详解1、input():获取控制台(任意形式)的输入。输出均为字符串类型。1.1、input() 与 list(input()) 的区别、及其相互转换方法2、print() :打印输出。3、整型int() :将指定进制…...

【论文速递】ICCV2021 - 基于超相关压缩实现实时高精度的小样本语义分割
【论文速递】ICCV2021 - 基于超相关压缩的小样本语义分割 【论文原文】:Hypercorrelation Squeeze for Few-Shot Segmentation 【作者信息】:Juhong Min Dahyun Kang Minsu Cho 获取地址:https://openaccess.thecvf.com/content/ICCV2021/…...
单例模式(Singleton Pattern)
目录 1.什么是单例模式: 2.单例模式存在的原因: 3.单例模式的优缺点: 4.创建方式: 1. 单线程单例模式立即创建(饿汉式): 2. 单线程单例模式延迟创建(懒汉式)…...

docker file和compose
文章目录1.dockerfile(单机脚本)1.概念2.原理3.dockerfile核心四步4.命令2.docker compose1.概念2.注意事项3.常用字段4.常用命令1.dockerfile(单机脚本) 1.概念 通过脚本,生成一个镜像,并运行对应的容器…...
如何解决thinkphp验证码不能显示问题?
thinkPHP做验证码这一块,可以使用自带的验证码扩展,具体步骤如下: 一、安装扩展 composer require topthink/think-captcha 二、模版中使用 将原来静态页面的验证码图片替换为{:captcha_img()},这个会自动生成验证码图片。 <div>{:captcha_img()}</div> 或者 &…...

Vue极简使用
Vue安装Vue模板语法安装Vue 安装nodejs 这里我安装的是14.5.4版本 https://nodejs.org/download/release/v14.15.4/解压后配置一下环境变量就行 安装cnpm镜像 (这个安装的版本可能过高,后面安装Vue可能出问题) npm install -g cnpm --registryhttps://registry…...

【Nacos】Nacos配置中心服务端源码分析
上文说了Nacos配置中心客户端的源码流程,这篇介绍下Nacos配置中心服务端的源码。 服务端的启动 先来看服务启动时干了啥? init()方法上面有PostConstruct,该方法会在ExternalDumpService实例化后执行。 com.alibaba.nacos.config.server.s…...

第十五章 栅格数据重分类、栅格计算器、插值分析
文章目录第十五章 栅格数据分析第一章 栅格数据重分类第一节 栅格数据重分类第二节 栅格重分类的使用第三节 重分类的使用中的空值使用第四节 重分类的案例:分类统计面积第五节 坡度矢量分级图生成第二章 栅格计算器第一节 栅格计算器介绍第二节 栅格计算器使用第三…...

CS5260测试版|CS5260demoboard|typec转VGA参考PCB原理图
CS5260测试版|CS5260demoboard|typec转VGA参考PCB原理图 CS5260是一款高度集成的TYPEC转VGA转换方案芯片。 CS5260输出端接口:外接高清VGA设备如:显示器投影机电视带高清的设备,广泛应用于 笔记本Macbook Air 12寸USB3.1输出端对外接高清VGA设备如:显示器投影机电视…...

winform开发心得
最近一直在从事winform的开发,每次都是需要从网上查找资料才能对应具体风格要求,现在总结一下。 ui方面可以使用CSkin对应的一套ui,使用步骤 1.在窗口界面,工具箱空白处点击右键,弹出菜单有个”选择项“,点…...

学习周报-2023-0210
文章目录一 在SUSE11sp3系统中将openssh从6升级到8一 需求二 系统环境三 部署流程1.上传编译安装的软件包2.安装 gcc编译软件3.安装依赖zlib4.安装依赖openssl5.安装openssh二 在CentOS-6.9配置apache服务(3)---虚拟主机配置一 定义二 系统环境三 基于域…...

百度富文本UE的问题集合
百度富文本编辑能上传视频成功但是在浏览器不能播放、显示的问题百度富文本视频封面空白问题百度富文本编辑器UMEditor 添加视频无法删除百度富文本编辑器结果存数据库取出来到js赋值报错怎么让浏览器重新加载修改过的JS文件,而不是沿用缓存里的百度富文本编辑能上传…...
在Linux上安装node-v14.17.3和npm-6.14.13
记录:374场景:在CentOS 7.9操作系统上,安装node-v14.17.3-linux-x64环境。包括node-v14.17.3和npm-6.14.13。node命令应用和npm命令应用。版本:JDK 1.8 node v14.17.3 npm 6.14.13官网地址:https://nodejs.org/下载地址…...

机器学习框架sklearn之特征降维
目录特征降维概念特征选择过滤式①低方差特征过滤②相关系数③主成分分析特征降维 0维 标量 1维 向量 2维 矩阵 概念 降维是指在某些限定条件下,降低随机变量(特征)个数,得到一组“不相关”主变量的过程 注:正是…...

java实现二叉树(一文带你详细了解二叉树的)
🎇🎇🎇作者: 小鱼不会骑车 🎆🎆🎆专栏: 《数据结构》 🎓🎓🎓个人简介: 一名专科大一在读的小比特,努力学习编程是我唯一…...

学弟学妹少走弯路,超完整算法刷题路线出炉
大家好,我是帅地。 本篇文章主要讲解下面三个事: 1、自己学习算法的一些经历 2、大家学习算法存在的一些普遍问题 3、给大家规划的算法刷题路线 一、算法学习往事 记得当初学了 C 语言就开始刷题了,刷题倒不是面试,而是为了…...

Windows截取gif动态图的软件 ScreenToGif 的安装、使用教程
一、概述 👉GIF(Graphics Interchange Format),又称图形交换格式,是一种公用的图像文件格式标准,于1987年由Compu Serve公司成功研发并推出。 👉GIF用于以超文本标志语言方式显示索引彩色图像&a…...

C++程序设计——多态:虚函数、抽象类、虚函数表
注:以下示例均是在VS2019环境下 一、多态的概念 通俗来讲,多态就是多种形态,当不同的对象去完成某个行为时,会产生出不同的状态。即不同继承关系的类对象,去调用同一函数时,产生不同的行为。 比如”叫“这…...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...