【c++】模板2—类模板
文章目录
- 类模板语法
- 类模板与函数模板区别
- 类模板中成员函数常见时机
- 类模板对象做函数参数
- 类模板与继承
- 类模板成员函数类外实现
- 类模板分文件编写
- 类模板与友元
类模板语法
类模板作用:
建立一个通用类,类中的成员数据类型可以不具体制定,用一个虚拟的类型来代表。
语法:
template<typename T>
类
解释:
template—声明创建模板
typename—表明其后面的符号是一种数据类型,可以用class代替
T—通用的数据类型,名称可以替换,通常为大写字母
#include<iostream>
using namespace std;
#include<string>template<class nameT,class ageT>
class person
{
public:person(nameT name, ageT age){this->m_name = name;this->m_age = age;}void showperson(){cout << "name:" << this->m_name << endl;cout << "age:" << this->m_age << endl;}nameT m_name;ageT m_age;
};void test()
{//通过类模板来实例化对象//指定nametype为string类型,agetype为int类型person<string, int> p1("张三", 18);p1.showperson();
}int main()
{test();system("pause");return 0;
}
类模板与函数模板区别
1、类模板没有自动类型推导的使用方式;
2、类模板在模板参数列表中可以有默认参数。
#include<iostream>
using namespace std;
#include<string>template<class nameT,class ageT=int>
class person
{
public:person(nameT name, ageT age){this->m_name = name;this->m_age = age;}void showperson(){cout << "name:" << this->m_name << endl;cout << "age:" << this->m_age << endl;}nameT m_name;ageT m_age;
};//1、类模板没有自动类型推导的使用方式
void test1()
{//person p("张三", 18);//错误!类模板使用时,不可以用自动类型推导person<string, int>p("张三", 18);//必须使用显示指定类型的方式,使用类模板p.showperson();
}//2、类模板在模板参数列表中可以有默认参数
void test2()
{person<string>p("李四",10);//类模板中的模板参数列表可以指定默认参数p.showperson();
}int main()
{test1();test2();system("pause");return 0;
}
类模板中成员函数常见时机
类模板中成员函数和普通类中成员函数创建时机是有区别的:
1、普通类中成员函数一开始就可以创建;
2、类模板中成员函数在调用时才创建。
#include<iostream>
using namespace std;
#include<string>class person1
{
public:void showperson1(){cout << "person1 show" << endl;}
};
class person2
{
public:void showperson2(){cout << "person2 show" << endl;}
};template<class T>
class myclass
{
public:T obj;//类模板中的成员函数,并不是一开始就创建的,而是在模板调用时再生成void func1(){obj.showperson1();}void func2(){obj.showperson2();}
};void test()
{myclass<person1>m;m.func1();//m.func2();//编译会出错,说明函数调用才会去创建成员函数,这行myclass<person1>m;的person1改成person2就可以编译成功
}int main()
{test();system("pause");return 0;
}
类模板对象做函数参数
类模板实例化出的对象,可以通过三种方式向函数中进行传参:
1、指定传入的类型——直接显示对象的数据类型;
2、参数模板化——将对象中的参数变为模板进行传参;
3、整个类模板化——将这个对象类型模板化进行传递。
#include<iostream>
using namespace std;
#include<string>template<class T1,class T2>
class person
{
public:person(T1 name, T2 age){this->m_name = name;this->m_age = age;}void showperson(){cout << "name:" << this->m_name << endl;cout << "age:" << this->m_age << endl;}T1 m_name;T2 m_age;
};//1、指定传入类型
void printperson1(person<string, int>& p)
{p.showperson();
}
void test1()
{person<string, int>p("张三", 18);printperson1(p);
}//2、参数模板化
template<class T1,class T2>
void printperson2(person<T1, T2>& p)
{p.showperson();cout << "T1的类型:" << typeid(T1).name() << endl;cout << "T2的类型:" << typeid(T2).name() << endl;
}
void test2()
{person<string, int>p("李四", 19);printperson2(p);
}//3、整个类模板化
template<class T>
void printperson3(T& p)
{p.showperson();cout << "T的类型:" << typeid(T).name() << endl;
}
void test3()
{person<string, int>p("王五", 20);printperson3(p);
}int main()
{test1();test2();test3();system("pause");return 0;
}
类模板与继承
当类模板碰到继承时,需要注意以下几点:
1、当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型;
2、如果不指定,编译器无法给子类分配内存;
3、如果想灵活指定出父类中T1的类型,子类也需编程类模板。
#include<iostream>
using namespace std;
#include<string>template<class T>
class dad
{T m;
};//class son1 :public dad//错误!必须要知道父类中的T类型,才能继承给子类
class son1 :public dad<int>//必须指定一个类型
{
};//如果想灵活指定父类中T类型,子类也需要变类模板
template<class T1,class T2>
class son2 :public dad<T2>
{
public:son2(){cout << "T1的类型:" << typeid(T1).name() << endl;cout << "T2的类型:" << typeid(T2).name() << endl;}
};void test()
{son1 s1;son2<int, char>s2;
}int main()
{test();system("pause");return 0;
}
类模板成员函数类外实现
类模板中成员函数类外实现时,需要加上模板参数列表。
#include<iostream>
using namespace std;
#include<string>//类内实现
template<class T1, class T2>
class person1
{
public:person1(T1 name, T2 age){this->m_name = name;this->m_age = age;}void showperson1(){cout << "姓名:" << this->m_name << endl;cout << "年龄:" << this->m_age << endl;}T1 m_name;T2 m_age;
};//类外实现
template<class T1, class T2>
class person2
{
public:person2(T1 name, T2 age);void showperson2();T1 m_name;T2 m_age;
};//构造函数类外实现
template<class T1, class T2>
person2<T1, T2>::person2(T1 name, T2 age)
{this->m_name = name;this->m_age = age;
}//成员函数类外实现
template<class T1, class T2>
void person2<T1, T2>::showperson2()
{cout << "姓名:" << this->m_name << endl;cout << "年龄:" << this->m_age << endl;
}void test()
{person2<string, int>p("张三", 18);p.showperson2();
}int main()
{test();system("pause");return 0;
}
类模板分文件编写
问题:
类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到。
解决:
解决方式1:直接包含.cpp源文件;
解决方式2:将声明和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制的。
第一种解决方式:
main.cpp文件
#include<iostream>
using namespace std;//第一种解决方式:直接包含源文件
#include"person.cpp"void test()
{person<string, int>p("张三", 18);p.showperson();
}int main()
{test();system("pause");return 0;
}
person.h文件
#pragma once
#include<iostream>
using namespace std;#include<string>
template<class T1, class T2>
class person
{
public:person(T1 name, T2 age);void showperson();T1 m_name;T2 m_age;
};
person.cpp文件
#include"person.h"template<class T1, class T2>
person<T1, T2>::person(T1 name, T2 age)
{this->m_name = name;this->m_age = age;
}template<class T1, class T2>
void person<T1, T2>::showperson()
{cout << "name:" << this->m_name << endl;cout << "age:" << this->m_age << endl;
}
第二种解决方式:
main.cpp文件
#include<iostream>
using namespace std;//第二种解决方式:将.h和.cpp的内容写在一起,将后缀名改为.hpp文件
#include"person.hpp"void test()
{person<string, int>p("张三", 18);p.showperson();
}int main()
{test();system("pause");return 0;
}
person.hpp文件
#pragma once
#include<iostream>
using namespace std;#include<string>template<class T1, class T2>
class person
{
public:person(T1 name, T2 age);void showperson();T1 m_name;T2 m_age;
};template<class T1, class T2>
person<T1, T2>::person(T1 name, T2 age)
{this->m_name = name;this->m_age = age;
}template<class T1, class T2>
void person<T1, T2>::showperson()
{cout << "name:" << this->m_name << endl;cout << "age:" << this->m_age << endl;
}
类模板与友元
全局函数类内实现——直接在类内声明友元即可;
全局函数类外实现——需要提前让编译器知道全局函数的存在。
#include<iostream>
using namespace std;
#include<string>//类外实现
//全局函数配合友元 类外实现——先做函数声明,下方再做模板定义,再做友元
template<class T1, class T2>class person;//如果声明了函数模板,可以将实现写在后面,否则将实现体写在类的前面让编译器提前看到
//template<class T1, class T2>void printperson2(person<T1, T2> p);template<class T1, class T2>
void printperson2(person<T1, T2> p)
{cout << "类外实现:" << endl;cout << "姓名:" << p.m_name << endl;cout << "年龄:" << p.m_age << endl;
}//通过全局函数 打印person信息
template<class T1, class T2>
class person
{//全局函数 类内实现friend void printperson1(person<T1, T2> p){cout << "类内实现:" << endl;cout << "姓名:" << p.m_name << endl;cout << "年龄:" << p.m_age << endl;}//全局函数 类外实现friend void printperson2<>(person<T1, T2> p);//加空模板参数列表public:person(T1 name, T2 age){this->m_name = name;this->m_age = age;}
private:T1 m_name;T2 m_age;
};void test()
{person<string, int>p1("张三", 18);printperson1(p1);person<string, int>p2("李四", 20);printperson1(p2);
}int main()
{test();system("pause");return 0;
}
相关文章:
【c++】模板2—类模板
文章目录类模板语法类模板与函数模板区别类模板中成员函数常见时机类模板对象做函数参数类模板与继承类模板成员函数类外实现类模板分文件编写类模板与友元类模板语法 类模板作用: 建立一个通用类,类中的成员数据类型可以不具体制定,用一个虚…...
基于SpringCloud的可靠消息最终一致性03:项目骨架代码(下)
上一节把整个项目的演示内容、项目结构、POM文件和配置文件都讲完了,接下来继续。 先安装并启动Nacos,然后在其中建立一个名为xiangwang-payment-dev.yaml的配置文件,内容为: # 指定运行环境 spring:autoconfigure:exclude: com.alibaba.druid.spring.boot.autoconfigure.D…...
linux如何彻底的删除文件
一、使用rm命令删除 直接用rm 先用ls -alt看下文件信息及拥有者等 可以看到拥有者是eve用户,所以在eve用户的终端中rm命令即可, 如果是root或者其他,则优先用root或其他账号进行删除 (base) eveEve:~$ ls -alt a.txt -rw-rw-r-- 1 eve eve …...
数据仓库Hive的安装和部署
1)去apache.hive.org官网下载hive 目前hive主要有三大版本,Hive1.x、Hive2.x、Hive3.x Hive1.x已经2年没有更新了,所以这个版本后续基本不会再维护了,不过这个版本已经迭代了很多年了,也是比较稳定的 Hive2.x最近一直…...
Python调用CANoe常见问题
一、Win32com已经安装成功但是在pycharm中提示错误 No module named win32com.clientPyCharm中出现unresolved reference的解决方法 一直提示需要升级pip版本Pywin32已成功安装,但仍提示没有win32com模块...
一起Talk Android吧(第五百零七回:图片滤镜ImageFilterView)
文章目录背景介绍功能介绍图片滤镜图片圆角图片缩放图片旋转图片平移各位看官们大家好,上一回中咱们说的例子是"如何调整组件在约束布局中的角度",这一回中咱们说的例子是" 图片滤镜ImageFilterView"。闲话休提,言归正转,…...
Java 解释器和即时解释器(JIT)之间的区别
区别是: 翻译 .class (字节码文件) 的粒度和方式不同 解释器是一个逐条解释并执行字节码指令的组件,每次**只翻译一条**指令并执行,然后再翻译下一条指令。 它的翻译粒度是一条指令,而且是按需翻译&#x…...
Acwing 蓝桥杯 第二章 二分与前缀和
今天来补一下之前没写的总结,题是写完了,但是总结没写感觉没什么好总结的啊,就当打卡了789. 数的范围 - AcWing题库思路:一眼二分,典中典先排个序,再用lower_bound和upper_bound维护相同的数的左界和右界就…...
CSDN原力增长规则解读 实测一个月
CSDN原力越来越难了,当然,这对生态发展来说也是好事。介绍下原力增长有哪些渠道吧。发布原创文章:10分/次,每日上限为15分、2篇回答问题:1分/次,每日上限2分,2回答发动态:1分/次&…...
HDMI协议介绍(三)--InfoFrame
目录 Auxiliary Video information (AVI) InfoFrame AVI InfoFrame包结构 Header Body 举个例子 附录 Audio InfoFrame Audio InfoFrame包结构 Header Body Vendor Specific InfoFrame Vendor Specific InfoFrame包结构 Header Body AVI/AUDIO/VSI Infoframe都…...
【RocketMQ】源码详解:Broker端消息储存流程、消息格式
消息存储流程 入口: org.apache.rocketmq.remoting.netty.NettyRemotingAbstract#processRequestCommand org.apache.rocketmq.broker.processor.SendMessageProcessor#asyncProcessRequest 消息到达broker后会经过netty的解码、消息处理器等,最后根据…...
IoT项目系统架构案例2
项目背景 1.这个项目是对之前的案例的升级改造参考:IoT项目系统架构案例_iot案例_wxgnolux的博客-CSDN博客2.基于方案1的项目实施过程中碰到的问题,对硬件设备标准化的理念及新的功能需求(如根据天气预报温度调水温,APP界面可操作性优化等)•采用目前IoT主流厂商的架…...
Vue echarts封装
做大屏的时候经常会遇到 echarts 展示,下面展示在 Vue2.7 / Vue3 中对 echarts (^5.4.0) 的简单封装。 文章首发于https://blog.fxss.work/vue/echarts封装.html,样例查看 echarts 封装使用 props 说明 参数说明类型可选值默认…...
蓝桥杯入门即劝退(二十二)反转字符(不走寻常路)
欢迎关注点赞评论,共同学习,共同进步! ------持续更新蓝桥杯入门系列算法实例-------- 如果你也喜欢Java和算法,欢迎订阅专栏共同学习交流! 你的点赞、关注、评论、是我创作的动力! -------希望我的文章…...
数据仓库Hive
HIve介绍 Hive是建立在Hadoop上的数据仓库基础构架。它提供了一系列的工具,可以用来进行数据提取转化加载,可以简称为ETL。 Hive 定义了简单的类SQL查询语言,称为HQL,它允许熟悉SQL的用户直接查询Hadoop中的数据…...
嵌入式 STM32 步进电机驱动,干货满满,建议收藏
目录 步进电机 1、步进电机驱动原理 2、步进电机驱动 3、步进电机应用 1、第一步:初始化IO口 2、设置行进方式 四、源码 步进电机 步进电机被广泛应用于ATM机、喷绘机、刻字机、写真机、喷涂设备、医疗仪器及设备、计算机外设及海量存储设备、精密仪器、工业…...
详讲函数.2.
目录 5. 函数的嵌套调用和链式访问 5.1 嵌套调用 5.2 链式访问 小结: 6. 函数的声明和定义 6.1 函数的声明: 6.2 函数的定义: 5. 函数的嵌套调用和链式访问 函数和函数之间可以根据实际的需求进行组合的,也就是互相调用的…...
行测-判断推理-图形推理-位置规律-旋转、翻转
短指针每次逆时针旋转60(排除法选C走人)长指针每次顺时针旋转120选C左上菱形每次顺时针旋转90(排除C D)右上每次旋转180(选B走人)左下每次保持不变右下每次逆时针旋转90选B左上和右上为左右翻转,…...
linux shell 入门学习笔记15 shell 条件测试
概念 shell的条件测试目的是得出真和假。 shell 提供的条件测试语法 test 命令 [] 中括号命令 语法*: test条件测试 test命令用来评估一个表达式,他的结果是真,还是假,如果条件为真,那么命令执行状态结果就为0&…...
Apollo(阿波罗)分布式配置安装详解
Apollo(阿波罗) Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性&#…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...
倒装芯片凸点成型工艺
UBM(Under Bump Metallization)与Bump(焊球)形成工艺流程。我们可以将整张流程图分为三大阶段来理解: 🔧 一、UBM(Under Bump Metallization)工艺流程(黄色区域ÿ…...
EasyRTC音视频实时通话功能在WebRTC与智能硬件整合中的应用与优势
一、WebRTC与智能硬件整合趋势 随着物联网和实时通信需求的爆发式增长,WebRTC作为开源实时通信技术,为浏览器与移动应用提供免插件的音视频通信能力,在智能硬件领域的融合应用已成必然趋势。智能硬件不再局限于单一功能,对实时…...
C++ 类基础:封装、继承、多态与多线程模板实现
前言 C 是一门强大的面向对象编程语言,而类(Class)作为其核心特性之一,是理解和使用 C 的关键。本文将深入探讨 C 类的基本特性,包括封装、继承和多态,同时讨论类中的权限控制,并展示如何使用类…...
Selenium 查找页面元素的方式
Selenium 查找页面元素的方式 Selenium 提供了多种方法来查找网页中的元素,以下是主要的定位方式: 基本定位方式 通过ID定位 driver.find_element(By.ID, "element_id")通过Name定位 driver.find_element(By.NAME, "element_name"…...
Pandas 可视化集成:数据科学家的高效绘图指南
为什么选择 Pandas 进行数据可视化? 在数据科学和分析领域,可视化是理解数据、发现模式和传达见解的关键步骤。Python 生态系统提供了多种可视化工具,如 Matplotlib、Seaborn、Plotly 等,但 Pandas 内置的可视化功能因其与数据结…...
联邦学习带宽资源分配
带宽资源分配是指在网络中如何合理分配有限的带宽资源,以满足各个通信任务和用户的需求,尤其是在多用户共享带宽的情况下,如何确保各个设备或用户的通信需求得到高效且公平的满足。带宽是网络中的一个重要资源,通常指的是单位时间…...
