C++ —— 模板类扩展

C++ —— 模板类扩展

  • 模板类的成员模板
  • 将模板类用作参数

模板类的成员模板

结构体中可以有结构体,类中可以有类和成员函数。那么,模板类中也应该可以有模板类模板函数
在类AA中再创建一个模板类模板函数
先创建模板类,代码如下:

#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) {}void show() {cout << "AA的show ~ m_x = " << m_x << ", m_y = " << m_y << endl;}template <class T>class BB{public:T m_b;// 可以用AA的模板参数T1、T2创建成员变量T1 m_bx;BB() {}void show() {cout << "BB的show ~ m_b = " << m_b << ", m_bx = " << m_bx << endl;}};BB<string> bb; // 对象bb就是类模板AA的成员template <typename T> // 再创建一个函数模板,这个T和BB中的T没有关系void show(T t) {cout << "模板函数show ~ t = " << t << endl;cout << "AA ~ m_x = " << m_x << ", m_y = " << m_y << endl;bb.show();}
};int main() {AA<int, string> aa(123, "你好");aa.show();aa.bb.m_b = "哈哈";aa.bb.m_bx = 666;aa.bb.show();aa.show<string> ("嘻嘻嘻");return 0;
}

运行结果如下:

AA的show ~ m_x = 123, m_y = 你好
BB的show ~ m_b = 哈哈, m_bx = 666
模板函数show ~ t = 嘻嘻嘻
AA ~ m_x = 123, m_y = 你好
BB的show ~ m_b = 哈哈, m_bx = 666

模板类中的成员模板,定义可以写在类的外面。修改后的代码如下:

#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) {}void show() {cout << "AA的show ~ m_x = " << m_x << ", m_y = " << m_y << endl;}template <class T>class BB{public:T m_b;// 可以用AA的模板参数T1、T2创建成员变量T1 m_bx;BB() {}void show();};BB<string> bb; // 对象bb就是类模板AA的成员template <typename T> // 再创建一个函数模板,这个T和BB中的T没有关系void show(T t);
};// 模板类中的成员模板,定义可以写在类的外面。
template <class T1, class T2>
template <class T>
void AA<T1, T2>::BB<T>::show() {{cout << "BB的show ~ m_b = " << m_b << ", m_bx = " << m_bx << endl;}
}template <class T1, class T2>
template <typename T>
void AA<T1, T2>::show(T t) {cout << "模板函数show ~ t = " << t << endl;cout << "AA ~ m_x = " << m_x << ", m_y = " << m_y << endl;bb.show();
}int main() {AA<int, string> aa(123, "你好");aa.show();aa.bb.m_b = "哈哈";aa.bb.m_bx = 666;aa.bb.show();aa.show<string> ("嘻嘻嘻");return 0;
}

运行结果跟之前保持一致:

AA的show ~ m_x = 123, m_y = 你好
BB的show ~ m_b = 哈哈, m_bx = 666
模板函数show ~ t = 嘻嘻嘻
AA ~ m_x = 123, m_y = 你好
BB的show ~ m_b = 哈哈, m_bx = 666

将模板类用作参数

C++的类模板主要是为了解决数据结构的问题。线性表有:链表数组、和队列。以链表数组为例,为了支持任意类型数据,最好的方法就是用类模板来实现,代码如下:

#include <iostream>
using namespace std;template <class T, int len> // 实际上,链表没有长度的说法,但为了演示,假定有一个长度
class LinkList {
public:T* m_head; // 定义链表头节点指针int m_len = len; // 指定表长度// 链表常用操作void insert() {cout << "LinkList 插入操作" << endl;}void ddelete() {cout << "LinkList 删除操作" << endl;}void update() {cout << "LinkList 更新操作" << endl;}
};template <class T, int len>
class Array{
public:T* m_data;int m_len = len;void insert() {cout << "Array 插入操作" << endl;}void ddelete() {cout << "Array 删除操作" << endl;}void update() {cout << "Array 更新操作" << endl;}
};int main() {return 0;
}

模板的目的就是代码重用,既然链表和数组的逻辑结构是一样的,那就把它们改成模板类的形式。目前模板LinkListArray,是为了兼容各种各样的数据类型,解决的是物理结构问题。接下来把它们再次模板化,是从逻辑角度来考虑的。C++支持模板的模板,意思是把模板名当成一种特殊的数据类型。实例化对象的时候,可以用模板签名作为参数,传给模板。示例代码如下:

#include <iostream>
using namespace std;template <class T, int len> // 实际上,链表没有长度的说法,但为了演示,假定有一个长度
class LinkList {
public:T* m_head; // 定义链表头节点指针int m_len = len; // 指定表长度// 链表常用操作void insert() {cout << "LinkList 插入操作" << endl;}void ddelete() {cout << "LinkList 删除操作" << endl;}void update() {cout << "LinkList 更新操作" << endl;}
};template <class T, int len>
class Array{
public:T* m_data;int m_len = len;void insert() {cout << "Array 插入操作" << endl;}void ddelete() {cout << "Array 删除操作" << endl;}void update() {cout << "Array 更新操作" << endl;}
};// 线性表模板类:其中,tabletype 表示 线性表类型,datatype 表示 线性表数据类型,len 表示 长度
// tabletype 不是一个普通的参数,而是模板,意思是这个参数要填模板名。
// 填什么样的模板名呢?填有两个参数的类模板名。并且,要求类模板的第一个参数是通用类型,第二个是非通用类型。
// 此外,class可以用typename代替,只是class更直观。
// tabletype只是一个模板名,用T1创建对象时,还需要指定具体的数据类型。
// 常见的做法是:具体的数据类型用模板参数从外面传进来
template<template<class, int>class tabletype, class datatype, int len> // 模板参数列表
class LinearList{
public:tabletype<datatype, len> m_table; // 创建线性表对象void insert() {m_table.insert();}void ddelete() {m_table.ddelete();}void update() {m_table.update();}
};int main() {// 创建线性表对象,容器类型为链表,链表的数据类型为int,链表长度为20LinearList<LinkList, int, 20> a;a.insert();a.ddelete();a.update();LinearList<Array, string, 20> b;b.insert();b.ddelete();b.update();return 0;
}

运行结果如下:

LinkList 插入操作
LinkList 删除操作
LinkList 更新操作
Array 插入操作
Array 删除操作
Array 更新操作

感谢浏览,一起学习!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Typora中实现自动编号

文章目录 在Typora中实现自动编号1. 引言2. 准备工作3. 自动编号的实现3.1 文章大纲自动编号3.2 主题目录&#xff08;TOC&#xff09;自动编号3.3 文章内容自动编号3.4 完整代码 4. 应用自定义CSS5. 结论 在Typora中实现自动编号 1. 引言 Typora是一款非常流行的Markdown编辑…

Oracle exp和imp命令导出导入dmp文件

目录 一. 安装 instantclient-tools 工具包二. exp 命令导出数据三. imp 命令导入数据四. expdp 和 impdp 命令 一. 安装 instantclient-tools 工具包 ⏹官方网站 https://www.oracle.com/cn/database/technologies/instant-client/linux-x86-64-downloads.html ⏹因为我们在…

小程序发版后,强制更新为最新版本

为什么要强制更新为最新版本&#xff1f; 在小程序的开发和运营过程中&#xff0c;强制用户更新到最新版本是一项重要的策略&#xff0c;能够有效提升用户体验并保障系统的稳定性与安全性。以下是一些主要原因&#xff1a; 1. 功能兼容 新功能或服务通常需要最新版本的支持&…

设计模式 创建型 原型模式(Prototype Pattern)与 常见技术框架应用 解析

原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;其核心思想在于通过复制现有的对象&#xff08;原型&#xff09;来创建新的对象&#xff0c;而非通过传统的构造函数或类实例化方式。这种方式在需要快速创建大量相似对象时尤为高效&#x…

办公 三之 Excel 数据限定录入与格式变换

开始-----条件格式------管理规则 IF($A4"永久",1,0) //如果A4包含永久&#xff0c;条件格式如下&#xff1a; OR($D5<60,$E5<60,$F5<60) 求取任意科目不及格数据 AND($D5<60,$E5<60,$F5<60) 若所有科目都不及格 显示为红色 IF($H4<EDATE…

黑马JavaWeb开发跟学(十四).SpringBootWeb原理

黑马JavaWeb开发跟学 十四.SpringBootWeb原理 SpingBoot原理1. 配置优先级2. Bean管理2.1 获取Bean2.2 Bean作用域2.3 第三方Bean 3. SpringBoot原理3.1 起步依赖3.2 自动配置3.2.1 概述3.2.2 常见方案3.2.2.1 概述3.2.2.2 方案一3.2.2.3 方案二 3.2.3 原理分析3.2.3.1 源码跟踪…

linux-26 文件管理(四)install

说一个命令&#xff0c;叫install&#xff0c;man install&#xff0c;install是什么意思&#xff1f;安装&#xff0c;install表示安装的意思&#xff0c;那你猜install是用来干什么的&#xff1f;猜一猜干什么的&#xff1f;安装软件&#xff0c;安装第三方软件&#xff0c;错…

Win11+WLS Ubuntu 鸿蒙开发环境搭建(二)

参考文章 penHarmony南向开发笔记&#xff08;一&#xff09;开发环境搭建 OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——标准系统移植指南&#xff08;一&#xff09; OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——小型系统芯片移植指南&#xff08;二&…

多文件比对

要比对多个存储目录下的文件是否存在重复文件&#xff0c;可以通过以下步骤实现 MD5 值的比对&#xff1a; 1. 提取文件路径 首先从你的目录结构中获取所有文件的路径&#xff0c;可以使用 find 命令递归列出所有文件路径&#xff1a;find /traixxxnent/zpxxxxx -type f >…

46. Three.js案例-创建颜色不断变化的立方体模型

46. Three.js案例-创建颜色不断变化的立方体模型 实现效果 知识点 Three.js基础组件 WebGLRenderer THREE.WebGLRenderer是Three.js提供的用于渲染场景的WebGL渲染器。它支持抗锯齿处理&#xff0c;可以设置渲染器的大小和背景颜色。 构造器 antialias: 是否开启抗锯齿&am…

【51单片机零基础-chapter6:LCD1602调试工具】

实验0-用显示屏LCD验证自己的猜想 如同c的cout,前端的console.log() #include <REGX52.H> #include <INTRINS.H> #include "LCD1602.h" int var0; void main() {LCD_Init();LCD_ShowNum(1,1,var211,5);while(1){;} }实验1-编写LCD1602液晶显示屏驱动函…

【GO基础学习】gin的使用

文章目录 模版使用流程参数传递路由分组数据解析和绑定gin中间件 模版使用流程 package mainimport ("net/http""github.com/gin-gonic/gin" )func main() {// 1.创建路由r : gin.Default()// 2.绑定路由规则&#xff0c;执行的函数// gin.Context&#x…

杰盛微 JSM4056 1000mA单节锂电池充电器芯片 ESOP8封装

JSM4056 1000mA单节锂电池充电器芯片 JSM4056是一款单节锂离子电池恒流/恒压线性充电器&#xff0c;简单的外部应用电路非常适合便携式设备应用&#xff0c;适合USB电源和适配器电源工作&#xff0c;内部采用防倒充电路&#xff0c;不需要外部隔离二极管。热反馈可对充电电流进…

Linux实验报告14-Linux内存管理实验

目录 一&#xff1a;实验目的 二&#xff1a;实验内容 1、编辑模块的源代码mm_viraddr.c 2、编译模块 3、编写测试程序mm_test.c 4、编译测试程序mm_test.c 5、在后台运行mm_test 6、验证mm_viraddr模块 一&#xff1a;实验目的 (1)掌握内核空间、用户空间&#xff…

供需平台信息发布付费查看小程序系统开发方案

供需平台信息发布付费查看小程序系统主要是为了满足个人及企业用户的供需信息发布与匹配需求。 一、目标用户群体 个人用户&#xff1a;寻找兼职工作、二手物品交换、本地服务&#xff08;如家政、维修&#xff09;等。 小微企业&#xff1a;推广产品和服务&#xff0c;寻找合…

overleaf写学术论文常用语法+注意事项+审阅修订

常用语法 导入常用的宏包 \usepackage{cite} \usepackage{amsmath,amssymb,amsfonts} \usepackage{algorithmic} \usepackage{algorithm} \usepackage{graphicx} \usepackage{subfigure} \usepackage{textcomp} \usepackage{xcolor} \usepackage{lettrine} \usepackage{booktab…

动态规划<八> 完全背包问题及其余背包问题

目录 例题引入---找到解决问题模版 LeetCode 经典OJ题 1.第一题 2.第二题 3.第三题 其余的一些背包问题 1.二维费用的背包问题 例题引入---找到解决问题模版 OJ 传送门 牛客 DP42 【模板】完全背包 画图分析: 使用动态规划解决(第二问与第一问的不同之处用绿色来标记) 1.…

TP8 前后端跨域访问请求API接口解决办法

报错&#xff1a;Access to XMLHttpRequest at http://www.e.com/api/v1.index/index?t1735897901267 from origin http://127.0.0.1:5500 has been blocked by CORS policy: Response to preflight request doesnt pass access control check: The value of the Access-Contr…

【前端系列】Pinia状态管理库

文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、Pinia状态管理库&#xff1a;☀️☀️☀️2.1 pinia基本使用① pinia充当中转站存放token② 使用步骤 2.1 axios请求拦截器 一、前言&#x1f680;&#x1f680;&#x1f680; ☀️ 回报不在行动之后&#xff0c;…

打造三甲医院人工智能矩阵新引擎(四):医疗趋势预测大模型篇 EpiForecast与DeepHealthNet合成应用

一、引言 1.1 研究背景与意义 在当今数字化时代,医疗领域积累了海量的数据,涵盖电子病历、医学影像、基因序列、临床检验结果等多源异构信息。这些数据蕴含着疾病发生发展、治疗反应、疫情传播等规律,为医疗趋势预测提供了数据基础。准确的医疗趋势预测能辅助医疗机构提前…