C++(12) 模板类、模板继承(严格模式和自由模式)

文章目录

      • 模版类
        • 1. 模版类
        • 2. 模版参数限制
        • 3. 模版继承
          • 3.1 严格模式
          • 3.2 自由模式
        • 4. 模版类的模版函数
        • 5. 返回值类型带有模版

模版类

1. 模版类
#include <iostream>using namespace std;/*
当前 Person 类型,声明了连个模版分别对应NameType 模版类型,名称可以看出,用于约束成员变量 name 的类型AgeType  模版类型,名称可以看出,用于约束成员变量 age 的类型模版类型充当数据类型占位符,在整个类中,成员变量,成员函数,构造函数都可以使用
*/
template <typename NameType, typename AgeType>
class Person
{
public:Person() {}Person(NameType name, AgeType age) : name(name), age(age) {}Person(const Person & person) : name(person.name), age(person.age) {}~Person() {}NameType getName() { return name; }void setName(NameType name) { this->name = name; }AgeType getAge() { return age; }void setAge(AgeType age) { this->age = age; }private:NameType name;AgeType age;
};int main(int argc, char const *argv[])
{/*Person 类型带有模版修饰,需要在使用之前明确模版对应的具体类型模版具备数据类型支持的多样性,同时一旦确定模版类型,严格遵守数据类型一致化原则Person 类型如何确定模版对应的具体数据类型格式:类名<模版对应具体数据类型> * 对象 = new 类型<模版对应具体数据类型>(...);Person<NameType, AgeType>*/// p1 明确告知编译器 NameType ==> string AgeType ==> int// 在后续的代码中,通过 p1 调用 Person 类内函数按照以上规则完成Person<string, int> *p1 = new Person<string, int>();p1->setName("布丁");p1->setAge(3);cout << "Name : " << p1->getName() << ", Age : " << p1->getAge() << endl;Person<string, int> *p2 = new Person<string, int>("张三", 14);cout << "Name : " << p2->getName() << ", Age : " << p2->getAge() << endl;delete p1;delete p2;return 0;
}
2. 模版参数限制

双重限制

  • 限制外部类型
  • 限制模版类型
#include <iostream>using namespace std;template <typename DataType, typename MsgType>
class Data
{
public:Data() {}Data(DataType value, MsgType msg) : value(value), msg(msg) {}Data(const Data &data) : value(data.value), msg(data.msg) {}~Data() {}DataType getValue() { return value; }void setValue(DataType value) { this->value = value; }MsgType getMsg() { return msg; }void setMsg(MsgType msg) { this->msg = msg; }private:DataType value;MsgType msg;
};/*
当前 test1 函数明确告知调用者,当前所需的参数为 Data
同时限制 Data 中对应的模版类型为 <int, string>
*/
void test1(Data<int, string> *data);/*
当前 test1 函数明确告知调用者,当前所需的参数为 Data
同时限制 Data 中对应的模版类型为 <double, string>
*/
void test1(Data<double, string> *data);int main(int argc, char const *argv[])
{/*双重限制*/Data<int, string> *d1 = new Data<int, string>(10, "别困!");Data<double, string> *d2 = new Data<double, string>(3.14, "别困!!");Data<char, string> *d3 = new Data<char, string>('G', "遵守数据类型一致化原则");test1(d1);test1(d2);/*test1 函数重载操作,所需函数有两种情况Data<int, string> *Data<double, string> *并没有支持Data<char, string> * 考虑到双重限制,分别对应外部类型和模版类型因此 d3 无法作为函数 test1 的实际参数【注意】请遵守数据类型一致化原则*/// test1(d3);delete d1;delete d2;delete d3;return 0;
}void test1(Data<int, string> *data)
{cout << "value : " << data->getValue() << ", Msg : " << data->getMsg() << endl;
}void test1(Data<double, string> *data)
{cout << "value : " << data->getValue() << ", Msg : " << data->getMsg() << endl;
}
3. 模版继承
3.1 严格模式
#include <iostream>using namespace std;/*
类带有模版,同时有子类继承当前类1. 自由模式子类带有和父类同名声明模版2. 严格模式【当前模式】子类在继承父类时,直接指定模版的具体类型,不得修改
*//*
MyCompare 类1. 声明了模版2. 声明纯虚函数3. MyCompare 是一个抽象类
*/
template <typename T>
class MyCompare
{
public:// 纯虚函数,并且使用了类声明的模版virtual bool compare(T t1, T t2) = 0;
};
/*
IntCompare 类1. 继承了 MyCompare 抽象类2. 继承父类的过程中,同时限制了模版对应的具体类型3. IntCompare 类没有声明模版IntCompare 目标是一个【实现类】1. 必须实现 Compare 函数2. 父类 MyCompare 已经明确限制模版对应的具体类型为 int 类型3. IntCompare 目标实现的函数bool compare(int t1, int t2)
*/
class IntCompare : public MyCompare<int>
{
public:bool compare(int t1, int t2){return t1 > t2;}
};int main(int argc, char const *argv[])
{/*bool compare(long t1, long t2) {...}在明确 模版对应的类型为 int 类型,实现上面的函数实例化的过程中,会出现报错:纯虚拟 函数 "MyCompare<T>::compare [其中 T=int]" 没有强制替代项*/IntCompare * ic = new IntCompare;cout << "ret : " << ic->compare(30, 20) << endl; // 1cout << "ret : " << ic->compare(10, 20) << endl; // 0return 0;
}
3.2 自由模式
#include <iostream>using namespace std;/*
类带有模版,同时有子类继承当前类1. 自由模式【当前模式】子类带有和父类同名声明模版2. 妻管严模式子类在继承父类时,直接指定模版的具体类型,不得修改
*//*
MyCompare 类1. 声明了模版2. 声明纯虚函数3. MyCompare 是一个抽象类
*/
template <typename T>
class BaseHandler
{
public:// 纯虚函数,并且使用了类名声明的模版virtual void handler(T t) = 0;
};/*
MyHander 继承抽象类 BaseHandler,同时1. 声明和 BaseHandler 同名模版2. 当前模版类型尚未明确3. 必须实现 void hander(T t) 函数
*/
template <typename T>
class MyHandler : public BaseHandler<T>
{
public:void handler(T t){cout << "数据情况 : " << t << endl;}
};int main(int argc, char const *argv[])
{// 实例化 MyHandler 类对象,需要指定模版对应的具体类型MyHandler<string> * m1 = new MyHandler<string>;m1->handler("零零零零");MyHandler<int> * m2 = new MyHandler<int>;m2->handler(14);delete m1;delete m2;return 0;
}
4. 模版类的模版函数
#include <iostream>using namespace std;template <typename T>
class Test
{
public:// 当前函数使用的模版为当前 Test 类声明的模版void handler(T t) { cout << "value : " << t << endl; }/*模版类内的函数,期望可以自定义模版,使用的模版数据形式,约束与当前类不同*/template <typename T2>void my(T2 t) { cout << "value : " << t << endl; }
};int main(int argc, char const *argv[])
{Test<string> * test = new Test<string>;test->handler("零零零零");/*my 函数对应的模版类型,由实际参数决定,并不是实例化 Test 类型决定*/test->my(3.14);return 0;
}
5. 返回值类型带有模版
#include <iostream>using namespace std;/*
K ==> Key   键
V ==> Value 值
*/
template <typename K, typename V>
class Data
{
public:Data() {}Data(K key, V value) : key(key), value(value) {}Data(const Data & data) : key(data.key), value(data.value) {}~Data() {}K getKey() { return key; }void setKey(K key) { this->key = key; }V getValue() { return value; }void setValue(V value) { this->value = value; }/*友元函数中,重载运算符操作,使用的模版并不是 Data 声明的模版而是函数自定义模版,通过实际参数 Data 类型中的模版情况,限制当前函数的模版类型【满足注意 Data 类型展示数据操作】*/template <typename K1, typename V1>friend ostream & operator<<(ostream & o, Data<K1, V1> * data);private:K key;V value;
};template <typename K1, typename V1>
ostream & operator<<(ostream & o, Data<K1, V1> * data)
{o << "Key : " << data->getKey() << ", Value : " << data->getValue();return o;
}template <typename K, typename V>
Data<K, V> *getData(K key, V value);int main(int argc, char const *argv[])
{string name = "MY";Data<string, int> * data = getData(name, 3);cout << data << endl;Data<double, int> * data1 = getData(6.18, 9999);cout << data1 << endl;delete data;delete data1;return 0;
}/*
外部函数自定义模版,返回值是 Data 类型,同时
利用当前函数的实际参数对 Data 中模版数据进行
约束限制,模版具体数据情况根据参数具体数据类型确定!
*/
template <typename K, typename V>
Data<K, V> * getData(K key, V value)
{return new Data<K, V>(key, value);
}

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

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

相关文章

C++ array容器用法详解

array 容器是 C++ 11 标准中新增的序列容器,简单地理解,它就是在 C++ 普通数组的基础上,添加了一些成员函数和全局函数。在使用上,它比普通数组更安全(原因后续会讲),且效率并没有因此变差。 和其它容器不同,array 容器的大小是固定的,无法动态的扩展或收缩,这也就意…

【SpringCloud】使用 Spring Cloud Alibaba 之 Sentinel 实现微服务的限流、降级、熔断

目录 一、Sentinel 介绍1.1 什么是 Sentinel1.2 Sentinel 特性1.3 限流、降级与熔断的区别 二、实战演示2.1 下载启动 Sentinel 控制台2.2 后端微服务接入 Sentinel 控制台2.2.1 引入 Sentinel 依赖2.2.2 添加 Sentinel 连接配置 2.3 使用 Sentinel 进行流控&#xff08;含限流…

SLAM ORB-SLAM2(19)特征点三角化

SLAM ORB-SLAM2(19)特征点三角化 1. 前言2. 初始化参数3. 计算投影矩阵4. 恢复三维点4.1. 计算推导4.2. Triangulate5. 检查三维点5.1. 检查三维点的深度值和视差角5.2. 检查空间点的重投影误差6. 最后处理1. 前言 在 《SLAM ORB-SLAM2(12)估算运动并初始地图点》 中了解到…

如何将cocos2d-x js打包部署到ios上 Mac M1系统

项目环境 cocos2d-x 3.13 xcode 12 mac m1 big sur 先找到你的项目 使用xcode软件打开上面这个文件 打开后应该是这个样子 执行编译运行就好了 可能会碰到的错误 在xcode11版本以上都会有这个错误&#xff0c;这是因为iOS11废弃了system。 将上面代码修改为 #if (CC_TARGE…

Java 面向对象进阶 16 接口的细节:成员特点和接口的各种关系(黑马)

成员变量默认修饰符是public static final的原因是&#xff1a; Java中接口中成员变量默认修饰符是public static final的原因是为了确保接口的成员变量都是公共的、静态的和不可修改的。 - public修饰符确保了接口的成员变量可以在任何地方被访问到。 - static修饰符使得接口…

vue-利用属性(v-if)控制表单(el-form-item)显示/隐藏

表单控制属性 v-if 示例&#xff1a; 通过switch组件作为开关&#xff0c;控制表单的显示与隐藏 <el-form-item label"创建数据集"><el-switch v-model"selectFormVisible"></el-switch></el-form-item><el-form-item label&…

Redis篇----第七篇

系列文章目录 文章目录 系列文章目录前言一、Redis 的回收策略(淘汰策略)?二、为什么 edis 需要把所有数据放到内存中?三、Redis 的同步机制了解么?四、Pipeline 有什么好处,为什么要用 pipeline?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍…

crontab history查看命令的执行时间

crontab crontab学习网站&#xff08;19. crontab 定时任务 — Linux Tools Quick Tutorial&#xff09; 例子 今天实际工作里用到的&#xff08;已经进行了防信息泄露处理 比如我现在希望每周三上午10:00之行一个php脚本 --gpt生成 00 10 * * 3 cd /home/user/project/r…

阿里云SSL免费证书到期自动申请部署程序

阿里云的免费证书只有3个月的有效期&#xff0c;不注意就过期了&#xff0c;还要手动申请然后部署&#xff0c;很是麻烦&#xff0c;于是写了这个小工具。上班期间抽空写的&#xff0c;没有仔细测试&#xff0c;可能存在一些问题&#xff0c;大家可以自己clone代码改改&#xf…

【大模型 数据增强】LLMAAA:使用 LLMs 作为数据标注器

【大模型 数据增强】LLMAAA&#xff1a;使用 LLMs 作为数据标注器 提出背景算法步骤1. LLM作为活跃标注者&#xff08;LLMAAA&#xff09;2. k-NN示例检索与标签表述化3. 活跃学习策略4. 自动重权技术 LLMAAA 框架1. LLM Annotator2. Active Acquisition3. Robust Training 总结…

SkyWalking之APM无侵入可观测原理分析

一、 简介&#xff08;为什么需要用到可观测能力&#xff09; 随着微服务的开发模式的兴起&#xff0c;早期的单体架构系统已拆分为很多的子系统&#xff0c;各个子系统封装为微服务&#xff0c;各服务间通过HTTP协议RESET API或者RPC协议进行调用。 在单体服务或者微服务较少的…

8:00面试,8:05就出来了 ,问的实在是....

从外包出来&#xff0c;没想到竟然死在了另一家厂子 自从加入这家公司&#xff0c;每天都在加班&#xff0c;钱倒是给的不少&#xff0c;所以我也就忍了。没想到12月一纸通知&#xff0c;所有人都不许加班&#xff0c;薪资直降30%&#xff0c;顿时有吃不起饭的赶脚。 好在有个…

AI推介-大语言模型LLMs论文速览(arXiv方向):2024.02.05-2024.02.10

相关LLMs论文大多都是应用型文章&#xff0c;少部分是优化prompt/参数量级等等… 有一些应用文还是值得参考的&#xff0c;当工作面临一个新的场景&#xff0c;可以学习下他人是如何结合LLMs与实际应用中的链接。 LLMs论文速览&#xff1a;2024.02.05-2024.02.10&#xff1a; …

ESP8266智能家居(2)——8266发布数据到mqtt服务器

1.公共服务器 学习物联网就离不开服务器&#xff0c;如果你资金充足的话&#xff0c;可以自己购买或者租用一个服务器。本次我选择&#xff0c;使用免费的公共MQTT服务器。它的端口及Broker信息如下&#xff1a; 网址为&#xff1a; 免费的公共 MQTT 服务器 | EMQ (emqx.com)h…

LLMChain使用 | RouterChain的使用 - 用本地大模型搭建多Agents

单个本地大模型搭建参考博客 单个Chain&#xff1a;面对一个需求&#xff0c;我们需要创建一个llmchain&#xff0c;设置一个prompt模板&#xff0c;这个chain能够接收一个用户input&#xff0c;并输出一个结果&#xff1b;多个Chain&#xff1a;考虑到同时面对多个需求&#x…

动态规划背包问题

前言 动态规划背包问题是一类经典的优化问题&#xff0c;涉及到选择物品以最大化某个目标值&#xff08;通常是价值或利润&#xff09;&#xff0c;同时受到某种约束&#xff08;如重量、体积或时间&#xff09;。背包问题可以分为多种类型&#xff0c;例如0-1背包问题、完全背…

第三百六十回

文章目录 1. 概念介绍2. 实现方法2.1 环绕效果2.2 立体效果 3. 示例代码4. 内容总结 我们在上一章回中介绍了"自定义SlideImageSwitch组件"相关的内容&#xff0c;本章回中将介绍两种阴影效果.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本…

设计模式-创建型模式-原型模式

原型模式&#xff08;Prototype Pattern&#xff09;&#xff1a;使用原型实例指定创建对象的种类&#xff0c;并且通过克隆这些原型创建新的对象。原型模式是一种对象创建型模式。原型模式其实就是从一个对象再创建另外一个可定制的对象&#xff0c;而且不需知道任何创建的细节…

微信小程序开发学习笔记——2.8媒体组件image的src三种引入方式

>>跟着b站up主“咸虾米_”学习微信小程序开发中&#xff0c;把学习记录存到这方便后续查找。 课程连接&#xff1a; https://www.bilibili.com/video/BV19G4y1K74d?p11 image&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/component/image.html 一…

如何在Python中执行Shell脚本?

Python执行Shell命令 1、背景概述2、Python集成Shell及数据交互 1、背景概述 Python作为一种强大的脚本语言&#xff0c;其易用性和灵活性使得它成为自动化任务的理想选择。在Python中执行Shell脚本可以实现一些操作系统级的功能&#xff0c;使程序更加灵活、易理解和易维护 在…