【类模板】类模板的特化

news/2024/9/15 17:19:51/ 标签: c++, 开发语言, 算法

一、类模板的泛化

与函数模板一样,类模板的泛化就是普通的模板,不具有特殊性的模板。
以下的类模板为泛化的版本

//类模板的泛化
template<typename T,typename U>
struct TC {//静态成员变量static int static_varible;  //声明TC() {std::cout << "TC泛化版本的构造函数\n";}void func1(); void func2();
};//类外实现func1
template<typename T,typename U>
void TC<T, U>::func1() {std::cout << "func1的泛化版本\n";
}//类外实现func2
template<typename T, typename U>
void TC<T, U>::func2() {std::cout << "func2的泛化版本\n";
}template<typename T,typename U>
int TC<T, U>::static_varible = 50; //定义(初始化)

这里采用的类内声明,类外定义的方法

二、类模板的全特化

1.类模板的全特化

我们可以在有泛化版本的前提下,加入一个全特化的版本,如下所示:

//类模板的全特化
template<>
struct TC<int,int> { //<>符号是必要的TC() {std::cout << "TC<int,int>的特化版本构造函数\n";}void func1() {std::cout << "TC<int,int>的特化版本func1函数\n";}void func2();//添加泛化版本中没有的函数void func3();
};

注意,我们在类外实现函数的时候不能加入 t e m p l a t e < > template<> template<>,否则会编译失败。

//类外实现func2
//注意全特化版本类外实现不能加template<>//template<>
void TC<int, int>::func2() {std::cout << "TC<int,int>的特化版本func2函数\n";}//类外实现fun3
void TC<int, int>::func3() {std::cout << "TC<int,int>的特化版本func3函数\n";
}

由于全特化版本的类已经和泛化版本的类区分开来了,因此可以添加上泛化版本没有的内容。
如我们在成员函数上增加了 f u n c 3 func3 func3函数。

2. 普通成员函数的全特化

我们这里以全特化 f u n c 1 func1 func1函数为例:

//普通成员函数的全特化
template<> //这里可加可不加
void TC<double, int>::func1() { //全特化func1成员函数std::cout << "普通成员函数TC<double,int>::func1的全特化\n";
};

成员函数的全特化可以忽略 t e m p l a t e < > template<> template<>,也可以使用。

注意,如果我们先对泛化版本添加了成员函数的全特化版本,那么我们就无法对泛化版本添加相同的全特化的类模板,因为类模板的成员函数已经被占用了。

如图:

template<> 
struct TC<double,int> { //此时TC的<double,int>版本部分内容已经被占用了TC();void func1();void func2();};

会编译失败
在这里插入图片描述

3.静态成员变量的全特化

对于静态成员函数的全特化,我们首先必须在类外定义静态成员函数的泛化版本,然后再加入全特化版本。

泛化版本的定义:

template<typename T,typename U>
int TC<T, U>::static_varible = 50; //定义(初始化)

加入全特化版本的静态成员变量:

//静态成员变量的全特化
template<> //这里可加可不加
int TC<double, int>::static_varible = 100; 

对于静态成员变量的全特化,与普通成员函数一样,已经占有了就不能再加入相同版本的全特化类模板了。

三、类模板的偏特化

函数模板不具有偏特化,而类模板可以进行偏特化。

1. 模板参数数量上的偏特化

我们可以指定类模板的某些参数类型,特殊对其进行偏特化:
下面是 T C TC TC类模板在参数数量上的偏特化版本:

//模板参数数量上的偏特化
template<typename U>
struct TC<float, U> {TC() {std::cout << "TC<float,U>偏特化版本的构造函数\n";}void fun1();
};
//类外实现
template<typename U>
void TC<float, U>::fun1() {std::cout << "TC<float,U>偏特化版本的func1函数\n";
}

通过调用,我们发现使用了偏特化版本

void Test() {TC<float,int>t;
}

如图所示:

在这里插入图片描述

2.模板参数范围上的偏特化

有时,对于一些特殊的类型参数我们要进行特殊处理,如
∗ ( 指针 ) , & ( 左值引用 ) , & & ( 右值引用 ) , c o n s t ( 常变量 ) *(指针),\&(左值引用),\&\&(右值引用),const(常变量) (指针),&(左值引用),&&(右值引用),const(常变量)
因此,我们就可以对这些变量加入偏特化版本:
下面实现一个偏特化的 T C < c o n s t T , U ∗ > TC<const \ T,U*> TC<const T,U>的版本:

//模板参数范围上的偏特化
template<typename T,typename U>
struct TC<const T, U*> { //限定T为const类型,U为指针TC() {std::cout << "TC<const T,U*>偏特化版本的构造函数\n";}void func1();
};//类外实现
template<typename T,typename U>
void TC<const T, U*>::func1() {std::cout << "TC<const T,U*>偏特化版本的func1函数\n";
}

而这样就能缩小范围,在调用时优先调用偏特化版本。
如下图所示:
:
优先使用了偏特化版本的构造函数。

当然,如果去掉了这个偏特化版本,将会调用泛化版本。

注释掉偏特化版本后,运行得到:

在这里插入图片描述
由于找不到全特化版本和偏特化版本,因此最终调用了泛化版本

3.其他

最后,对于偏特化版本的话,不存在对成员函数或静态成员变量的偏特化。
以下代码无法通过编译:

//不存在对成员函数的偏特化
template<typename U>
void TC<double, U>::func2() {std::cout << "TC<double,U>偏特化版本的func2函数\n";
}

http://www.ppmy.cn/news/1519918.html

相关文章

【Java EE】JVM

目录 1. JVM简介 2.JVM运行流程 3.JVM运行时数据区 3.1 堆&#xff08;线程共享&#xff09; 3.2 Java虚拟机栈&#xff08;线程私有&#xff09; 1. JVM简介 JVM是 Java Virtual Machine 的简称&#xff0c;意为Java虚拟机。 虚拟机是指通过软件模拟的具有完整硬件功能的…

python-简单的dos攻击

前言 这个是DOS攻击学习(注意&#xff1a;千万别去攻击有商业价值的服务器或应用&#xff0c;不然会死的很惨(只有一个IP通过公网访问容易被抓),前提是网站没有攻击防御) 创建一个以python编写的后端web服务(好观察) 安装flask pip install flask from flask import Flaskapp …

Android使用前台服务

Android使用前台服务 服务几乎都是在后台运行的&#xff0c;一直以来它都是默默地做着辛苦的工作。但是服务的系统优先级还是比较低的&#xff0c;当系统出现内存不足的情况时&#xff0c;就有可能会回收掉正在后台运行的服务。 如果你希望服务可以一直保持运行状态&#xff…

使用golang的AST编写定制化lint

什么是lint &#xff08;来自wiki&#xff09;在计算机科学中&#xff0c;lint是一种工具程序的名称&#xff0c;它用来标记源代码中&#xff0c;某些可疑的、不具结构性&#xff08;可能造成bug&#xff09;的段落。它是一种静态程序分析工具&#xff0c;最早适用于C语言&…

【13年12月CCF计算机软件能力认证】:出现次数最多的数、ISBN号码、最大的矩形、有趣的数、I‘m stuck!

题目概括出现次数最多的数暴力枚举&#xff0c;非常简单ISBN号码直接模拟&#xff0c;非常简单最大的矩形用到双指针&#xff08;优化枚举&#xff09;&#xff0c;非常简单有趣的数用到了数学知识排列组合&#xff0c;有一定思维难度I’m stuck!我用到了两个dfs来解决&#xf…

【区块链 + 供应链】广汽本田区块链合同供应链管理系统 | FISCO BCOS应用案例

广汽本田是国内汽车制造的龙头&#xff0c;每年销售额超千亿级别&#xff0c;每年的合同采购规模量在百亿以上。企业内部采用传 统的中心化方式管理合同&#xff0c;由于涉及部门众多&#xff0c;需要管理的合同要素也各不相同&#xff0c;造成信息不集中、合同版本众多、 合同…

C#中lock(this)与lock(private object)区别

前言 在使用多线程编程时&#xff0c;我们会对代码关键部分确保其一次只由一个线程执行&#xff0c;对于防止争用条件和保持数据完整性至关重要。在C#中&#xff0c;lock 语句就是用于通过同步对共享资源的访问来实现此目的工具。本文介绍lock(this) 与lock(private object) 两…

重新修改 Qt 项目的 Kit 配置

要重新修改 Qt 项目的 Kit 配置&#xff0c;你可以按照以下步骤进行操作&#xff1a; 1. 打开 Qt Creator 首先&#xff0c;启动 Qt Creator&#xff0c;确保你的项目已经打开。 2. 进入项目设置 在 Qt Creator 中&#xff0c;点击菜单栏的 “Projects” 标签&#xff08;通…

Spark MLlib模型训练—回归算法 Decision tree regression

Spark MLlib模型训练—回归算法 Decision tree regression 在机器学习中,决策树是一种常用且直观的模型,广泛应用于分类和回归任务。决策树回归 (Decision Tree Regression) 通过将数据集分割成多个区域,构建一棵树形结构,以预测目标变量的连续值。本文将详细探讨 Spark 中…

【Eureka】搭建Eureka Server,实现服务注册和服务发现

1. Eureka介绍 Eureka是NetflixOSS套件中关于服务注册和发现的解决⽅案.SpringCloud对Eureka进⾏了集成,并作为优先推荐⽅案进⾏宣传,虽然⽬前Eureka2.0已经停⽌维护,新的微服务架构设计中,也不再建议使用,但是⽬前依然有⼤量公司的微服务系统使⽤Eureka作为注册中⼼. 官方文…

数据访问:JPA

文章目录 JPA的由来JPA是什么Spring Data JPA快速上手 JPA的由来 ORM框架能够将Java对象映射到关系型数据库中&#xff0c;能够直接持久化复杂的 Java对象。ORM框架的出现&#xff0c;可以让开发者从数据库编程中解脱出来&#xff0c;把更多的精力放在业务模型与业务逻辑上。目…

k8s-pod 实战八 (gRPC 探测详细分析)

gRPC 探测详细分析 在 Kubernetes 中,探针(Probe)用于检查应用程序的健康状态和就绪状态。尽管 Kubernetes 原生支持 HTTP 和 TCP 探针,但对于 gRPC 服务,你需要借助第三方工具来实现探测。grpc-health-probe 是一个常用的工具,它专门用于探测 gRPC 服务的健康状态。 实…

KeePassXC软件简介

KeePassXC 是一款开源且免费的跨平台密码管理器&#xff0c;它允许用户在不同的网站和服务上使用多个不同的密码&#xff0c;而无需记住它们。用户只需要记住一个主密码或者持有一个密钥文件&#xff0c;就可以访问所有密码的加密数据库。KeePassXC 支持 AES 加密算法&#xff…

《C++20 特性综述》

《C20 特性综述》 在编程世界中&#xff0c;C一直以其强大的性能和灵活性占据着重要地位。随着时间的推移&#xff0c;C不断发展和演进&#xff0c;C20 带来了一系列令人瞩目的新特性&#xff0c;为开发者提供了更强大的工具和更高效的编程方式。 一、概念&#xff08;Concep…

大模型技术 | 基于 Langchain 和 Streamlit,构建多 PDF RAG 聊天机器人

与 PDF 互动是很酷的。你可以与你的笔记、书籍和文档等进行聊天。 本文将帮助你构建一个基于 Multi RAG Streamlit 的 Web 应用程序&#xff0c;通过对话 AI 聊天机器人来读取、处理和互动PDF数据。 以下是该应用程序的工作步骤&#xff0c;用简单的语言进行说明。 配置必要的…

JDK原理

当我们谈论JDK&#xff08;Java Development Kit&#xff09;的原理时&#xff0c;实际上是在探讨Java语言及其开发环境背后的技术和设计思想。JDK是Java编程语言的核心工具包&#xff0c;它包含了Java运行环境&#xff08;JRE&#xff09;、Java编译器&#xff08;javac&#…

2 html5 浏览器已经支持的新API

HTML5规范下很多API浏览器都已经支持&#xff0c;这里我们列举几个很常用的浏览器支持的API: 1 tab页之间通信: BroadcastChannel(channelName); 可用于多个不同浏览器tab页之间通信。实例化的时候Channel名称必须相同。 const broadcastChannel new BroadcastChannel(myC…

39次8.29(了解docker-compose,docker-compose编排容器,配置harbor服务)

1.使用使用docker-compose编排容器 1.YAML ⽂件的格式和语法 1&#xff09;YAML ⽂件格式 yaml 是⼀种标记语⾔很直观的数据序列化格式&#xff0c;可读性很⾼。 类似于 xml 描述性语⾔&#xff0c;语法⽐xml简单的很多。 yaml 数据结构通过缩进进⾏表示&#xff0c;连续的…

金九银十来了,你准备好了吗?——迎接技术行业的旺季

每年的九月和十月&#xff0c;对于技术行业来说&#xff0c;是一个特别的时期。这个时期被业界称为“金九银十”&#xff0c;意味着招聘和项目开发的高峰期。对于技术人员而言&#xff0c;这不仅是一个职业发展的黄金时期&#xff0c;也是技术能力提升和职业规划的关键时刻。那…

RAG中pdf解析的方法全览

RAG中解析PDF的方法 一 pdf格式都有哪些 1.机器生成的pdf文件&#xff0c;包含图像&#xff0c;文本&#xff0c;可以被编辑 2.传统扫描文档&#xff0c;表现为图像&#xff0c;不能被编辑 3.带OCR的扫描文档。可能转OCR的过程中带入了错误。 二 pdf解析全科指南 全面指南…