【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(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性&#…...
突破效率瓶颈:LeagueAkari游戏辅助工具的五大核心能力
突破效率瓶颈:LeagueAkari游戏辅助工具的五大核心能力 【免费下载链接】LeagueAkari ✨兴趣使然的,功能全面的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/LeagueAkari LeagueAk…...
Phi-3-vision-128k-instruct开源价值:可审计、可修改、可私有化部署的多模态底座
Phi-3-vision-128k-instruct开源价值:可审计、可修改、可私有化部署的多模态底座 1. 模型简介 Phi-3-Vision-128K-Instruct 是一个轻量级的开放多模态模型,属于Phi-3模型家族的最新成员。这个模型建立在高质量的数据集基础上,包括合成数据和…...
从零到六级:系统化英语学习路径全解析
1. 零基础英语学习者的正确打开方式 很多朋友刚开始学英语时,都会陷入一个误区:一上来就背单词、学语法。我见过太多人抱着厚厚的单词书从abandon开始背,结果一个月后还在abandon。这种学习方式不仅效率低下,还特别容易打击学习积…...
企业级仓库管理系统设计:SpringBoot后端与Vue前端的完美结合
企业级仓库管理系统设计:SpringBoot后端与Vue前端的深度实践 在数字化转型浪潮中,企业级仓库管理系统正经历着从传统单机版向云原生架构的跃迁。本文将深入探讨如何基于SpringBoot和Vue技术栈构建高性能、可扩展的现代仓库管理系统,分享架构设…...
一键部署Qwen3-4B:打造属于你的极速、轻量级AI文本助手
一键部署Qwen3-4B:打造属于你的极速、轻量级AI文本助手 你是否曾经想过,拥有一个反应迅速、逻辑清晰、能帮你写代码、改文案、做翻译的私人AI助手,但又担心它太“重”,部署麻烦,或者运行起来慢吞吞? 今天…...
AI供应链信任革命:破解可信难题
AI供应链信任革命:TAIBOM如何破解AI系统“可信难题” 随着AI技术在软件工程中的广泛应用,AI系统的可信性问题日益凸显。TAIBOM(Trustworthy AI Bill of Materials)作为一种新兴技术框架,旨在通过透明化AI供应链的组件和…...
五款优质WordPress原创主题
市面上WordPress主题品类繁多,不同主题针对不同建站需求打造专属特性。以下精选五款原创WordPress主题,深度解析每款主题的核心特色与核心优势,帮你精准匹配建站方案。一、Grace主题 —— 优雅大气的高品质WordPress主题Grace主题主打优雅大气…...
FlowState Lab 时空波动仪快速部署教程:3步搭建Python开发环境
FlowState Lab 时空波动仪快速部署教程:3步搭建Python开发环境 1. 引言 最近在AI开发者圈子里,FlowState Lab的时空波动仪项目引起了不小的关注。作为一个专注于时间序列分析和预测的开源工具,它特别适合处理金融、气象、物联网等领域的数据…...
同济版高数笔记:边界点VS聚点,一张图搞定所有疑问(含易错题分析)
同济版高数笔记:边界点VS聚点,一张图搞定所有疑问(含易错题分析) 刚接触高等数学的点集拓扑概念时,许多同学会被"边界点"和"聚点"这对双胞胎般的定义搞得晕头转向。同济大学《高等数学》教材中这两…...
SiameseUIE完整指南:test.py可扩展性设计——支持批量文本处理改造
SiameseUIE完整指南:test.py可扩展性设计——支持批量文本处理改造 1. 为什么需要改造test.py? SiameseUIE镜像开箱即用,但原始test.py只面向单次验证场景:它内置5个固定测试样例,逐条运行、逐条打印结果,…...
