【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(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性&#…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...

基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...