模板-C++提高编程

C++的一种编程思想称为泛型编程,用到的技术就是模板

C++提供两种模板:函数模板和类模板。

1.函数模板

1.函数模板作用

建立一个通用函数,其返回值类型和形参类型可以用一个虚拟的类型来代替,提高代码复用性,将类型参数化。

2.语法

template<typename T>
//函数声明或定义

template--声明创建模板

typename--表明其后面的符号是一种数据类型,可以用class代替

T--通用的数据类型,名称可以替换,通常为大写字母

3.例子

未应用模板(代码复杂,通用性差)

void intswap(int& a, int& b)
{int c;c = a;a = b;b = c;
}
void doubleswap(double& a, double& b)
{double c;c = a;a = b;b = c;
}

应用模板(代码简洁,通用性强)

注意:函数模板一次只能对应一个函数,也就是说T不能多次重复使用

template<typename T>
void swap(T& a, T& b)
{T c;c = a;a = b;b = c;
}

4.模板使用方式

1.自动类型推导

swap(a,b);

2.显示指定类型

swap<int>(a,b);

5.注意事项

1.自动类型推导

必须推导出一只的数据类型T才可以使用

反例:

#include<iostream>
using namespace std;
#include<string>
template<typename T>
void swap(T& a, T& b)
{T c;c = a;a = b;b = c;
}
int main()
{int a=0;char b = '12';swap(a, b);return 0;
}

2.T的类型必须确定

模板必须要确定T的类型,才可以使用

反例:

#include<iostream>
using namespace std;
#include<string>
template<typename T>
void swap()
{cout << "swap" << endl;
}
int main()
{swap();return 0;
}

6.案例

1.题目

对数组进行降序排序

2.代码
#include<iostream>
using namespace std;
#include<string>
template<typename T>
void sort(T a[],int len)
{T temp;int max ;for (int i = 0; i < len; i++){max = i;for (int j = i; j < len; j++){if (a[j] > a[max]){temp = a[j];a[j] = a[max];a[max] = temp;}}}
}
int main()
{char c[6] = "badce";sort(c,5);cout << c << endl;int a[6] = {4,5,2,3,1};sort(a, 5);for(int i=0;i<5;i++)cout << a[i] << endl;return 0;
}
3.结果

7.普通模板与函数模板区别

·普通函数可以发生自动类型转换(隐式类型转换)

·函数模板调用时,如果利用自动类型推导,则不会发生隐式类型转换

·如果利用显示指定类型的方式,可以发生隐式类型转换

1.普通函数隐式类型转换
#include<iostream>
using namespace std;
#include<string>
int fun(int a, int b)
{return a + b;
}
int main()
{int a = 10;char c = 'c';//a=97,c=99cout << fun(a, c) << endl;return 0;
}

2.自动类型推导不可以使用
#include<iostream>
using namespace std;
#include<string>
template<typename T>
int fun(T a, T b)
{return a + b;
}
int main()
{int a = 10;char c = 'c';cout << fun(a, c) << endl;return 0;
}

3.显式指定类型可以使用
#include<iostream>
using namespace std;
#include<string>
template<typename T>
int fun(T a, T b)
{return a + b;
}
int main()
{int a = 10;char c = 'c';cout << fun<int>(a, c) << endl;return 0;
}

4.建议

建议使用显式指定类型的方式调用,这种更加明确。

8.普通函数与函数模板调用规则

1.函数模板可以发生重载
1.普通函数与函数模板重载
#include<iostream>
using namespace std;
#include<string>
template<typename T>
void fun(T a)
{cout << "函数模板" << endl;
}
void  fun()
{cout << "普通函数" << endl;
}
int main()
{fun(1);fun();return 0;
}

2.函数模板之间的重载
#include<iostream>
using namespace std;
#include<string>
template<typename T>
void fun(T a)
{cout << "函数模板" << endl;
}
template<typename T>
void fun(T a,T b)
{cout << "重载函数模板" << endl;
}
int main()
{fun(1);fun(1, 1);return 0;
}
2.调用优先级

如果普通函数和函数模板都可以调用,优先调用函数模板

#include<iostream>
using namespace std;
#include<string>
template<typename T>
void fun(T a)
{cout << "函数模板" << endl;
}
void  fun( int a)
{cout << "普通函数" << endl;
}
int main()
{fun(1);return 0;
}

注意:就算普通函数只有一个声明也不会调用函数模板(会报错)。

#include<iostream>
using namespace std;
#include<string>
template<typename T>
void fun(T a)
{cout << "函数模板" << endl;
}
void  fun(int a);
int main()
{fun(1);return 0;
}

3.强制调用模板函数

通过空模板参数列表,强制调用函数模板

fun<>(1);
4.发生隐式类型转换时的优先级

当普通函数发生隐式类型转换时,会优先调用函数模板(程序会使用最优选择)

#include<iostream>
using namespace std;
#include<string>
template<typename T>
void fun(T a)
{cout << "函数模板" << endl;
}
void fun(char a)
{cout << "普通函数调用" << endl;
}
int main()
{fun(1);return 0;
}

2.类模板

1.定义

建立一个通用类,类中的成员数据类型可以不具体指定,用一个虚拟的类型来代替。

2.语法

template<typename T>
//类

template--声明创建模板

typename--表明其后面的符号是一种数据类型,可以用class代替

T--通用的数据类型,名称可以替换,通常为大写字母

3.例子

#include<iostream>
using namespace std;
#include<string>
template<class A,class B>
class person
{
public:person(A name, B age){this->name = name;this->age = age;}void show(){cout << this->name << this->age << endl;}A name;B age;
};
int main()
{person<string, int>p1("孙悟空", 999);p1.show();return 0;
}

4.类模板与函数模板区别

1.类模板不可以使用自动类型推导,只能自己设置类型。

2.类模板的模板参数列表中可以默认参数

模板参数表:即为尖括号里面的

template<class A,class B>

默认参数

template<class A,class B=int>

5.类模板中的成员函数创建时机

只要不去调用,就不会创建,所以a.fun()不会报错

#include<iostream>
using namespace std;
#include<string>
template<class A>
class person
{
public:A a;void fun(){a.fun1();}
};
int main()
{return 0;
}

6.类模板对象做函数参数

#include<iostream>
using namespace std;
#include<string>
template<class A,class B>
class person
{
public:A name;B age;person(A name, B age){this->name = name;this->age=age;}void show(){cout << this->name << endl;cout << this->age << endl;}
};
void fun(person<string, int>&p1)
{p1.show();
}
int main()
{person<string, int>p1("孙悟空", 100);fun(p1);return 0;
}

此时的函数参数应该是“person<string, int>&p1”

7.函数模板参数模板化

使用函数模板来提高复用性

#include<iostream>
using namespace std;
#include<string>
template<class A,class B>
class person
{
public:A name;B age;person(A name, B age){this->name = name;this->age=age;}void show(){cout << this->name << endl;cout << this->age << endl;}
};
template<class T1,class T2>
void fun(person<T1, T2>&p1)
{p1.show();
}
int main()
{person<string, int>p1("孙悟空", 100);fun(p1);return 0;
}

1.类型显示方法

如果想显示出自动类型转换的类型是什么,可以用这个方法

#include<iostream>
using namespace std;
#include<string>
template<class A,class B>
class person
{
public:A name;B age;person(A name, B age){this->name = name;this->age=age;}void show(){cout <<"姓名:" << this->name << endl;cout << "年龄:" << this->age << endl;}
};
template<class T1,class T2>
void fun(person<T1, T2>&p1)
{p1.show();cout <<"T1的类型:" << typeid(T1).name() << endl;cout <<"T2的类型:" << typeid(T2).name() << endl;
}
int main()
{person<string, int>p1("孙悟空", 100);fun(p1);return 0;
}

8.将做参数的整个类都模板化

#include<iostream>
using namespace std;
#include<string>
template<class A,class B>
class person
{
public:A name;B age;person(A name, B age){this->name = name;this->age=age;}void show(){cout <<"姓名:" << this->name << endl;cout << "年龄:" << this->age << endl;}
};
template<class T>
void fun(T &p1)
{p1.show();cout << "T的数据类型:" << typeid(T).name() << endl;
}
int main()
{person<string, int>p1("孙悟空", 100);fun(p1);return 0;
}

9.类模板与继承

父类如果是一个模板,子类在继承时需要指出他的数据类型

1.手动指定数据类型
#include<iostream>
using namespace std;
#include<string>
template<class T>
class base
{
public:T a;
};
class son :public base<int>
{};
int main()
{return 0;
}
2.将子类也变为模板
#include<iostream>
using namespace std;
#include<string>
template<class T>
class base
{
public:T a;
};
template<class T1,class T2>
class son :public base<T2>
{
public:T1 a;
};
int main()
{son<string, int>p1;return 0;
}

10.类模板的函数类外实现

1.构造函数的类外实现
#include<iostream>
using namespace std;
#include<string>
template<class T1,class T2>
class person
{
public:T1 name;T2 age;person(T1 name, T2 age);
};
template<class T1,class T2>
person<T1,T2>::person(T1 name,T2 age)
{this->name = name;this->age = age;
}
int main()
{return 0;
}
2.成员函数的类外实现
#include<iostream>
using namespace std;
#include<string>
template<class T1,class T2>
class person
{
public:T1 name;T2 age;person(T1 name,T2 age);void fun();
};
template<class T1, class T2>
person<T1, T2>::person(T1 name, T2 age)
{this->name = name;this->age = age;
}
template<class T1,class T2>
void person<T1, T2>::fun()
{cout << name << endl;cout << age << endl;
}
int main()
{person<string, int>p("埃里给", 18);p.fun();return 0;
}

11.类模板分文件编写

该程序包含一个头文件和一个源文件,头文件负责函数实现,源文件负责函数调用

.hpp后缀名:约定俗成的包含类模板的声明与实现。

1.头文件(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 show();T1 name;T2 age;
};
template<class T1, class T2>
person<T1, T2>::person(T1 name, T2 age)
{this->name = name;this->age = age;
}
template<class T1, class T2>
void person<T1, T2>::show()
{cout << name << endl;cout << age << endl;
}
2.源文件
#include"person.hpp"
int main()
{person<string,int>p("埃里给", 18);p.show();return 0;
}
3.输出结果

12.类模板与友元

不想写了,想写的时候补上

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

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

相关文章

基于Asp.net的物流配送管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

顺序表和链表的对比(一)

前言 今天给小伙伴们分享的是在数据结构中顺序表和链表的对比。它们在计算机科学和软件开发中具有广泛的应用&#xff0c;是理解更复杂数据结构&#xff08;如栈、队列、树、图等&#xff09;的基础。这次将会给大家从定义初始化&#xff0c;以及功能增删查改上进行详细对比&a…

星越L_外后视镜使用讲解

目录 1.外后视镜调节 2后视镜折叠 3.后视镜加热 1.外后视镜调节 L控制左边后视镜调节,上下拨动调整视野,一般此镜左右21分,上下55开。 R控制左边后视镜调节,上下拨动调整视野,一般此镜左右13分,上下55开。 2后视镜折叠 车辆解锁自动展开 车辆关闭自动折叠 严寒天气…

DevOps实践:持续集成与持续部署完全指南

文章目录 引言&#xff1a;从人工到自动化的进化革命一、CI/CD核心认知升级1.1 持续集成 vs 持续部署 vs 持续交付1.2 中小团队为什么要实施CI/CD&#xff1f; 二、CI/CD工具链选型指南2.1 中小团队推荐技术栈2.2 工具对比决策矩阵 三、实战五步构建企业级流水线3.1 基础环境搭…

【数据结构】数据结构,算法 概念

0.本篇问题&#xff1a; 数据、数据元素、数据对象、数据项之间的基本关系&#xff1f;ADT是什么&#xff1f;数据结构的三要素&#xff1f;数据的逻辑结构有哪些&#xff1f;数据的存储结构有哪些&#xff1f;算法的五个特征&#xff1f;O(1) O(logn) O(n^n) O(n) O(n^2…

同步Oracle及mysql至KADB的KFS配置文件参考

Oracle源端flysync.ini文件 注意&#xff1a;oracle用户名大写 mysql源端flysync.ini文件 附&#xff1a;目标端KADB的flysync.ini文件 [m_kes_3113] 源端为KES kufl-port3113 datasource-typekingbase rolemaster replication-host10.4.43.53 replication-port54321 …

PECL(Positive Emitter-Coupled Logic)电平详解

一、PECL电平的定义与核心特性 PECL&#xff08;正射极耦合逻辑&#xff09;是一种基于 射极耦合逻辑&#xff08;ECL&#xff09;技术 的高速差分信号标准&#xff0c;采用 正电源供电&#xff08;如5V或3.3V&#xff09;。其核心特性包括 高速传输、低噪声、强抗干扰能力&am…

以 ArcGIS Pro 为笔,绘就水墨地图画卷

一、引言 水墨画&#xff0c;作为中国传统绘画艺术的瑰宝&#xff0c;以其独特的韵味和表现力&#xff0c;在艺术领域占据着重要地位。它通过水与墨的交融&#xff0c;展现出山水之间的灵动与韵味。 而将这种艺术形式与现代地理信息系统&#xff08;GIS&#xff09;技术相结合…

软考网络安全专业

随着信息技术的迅猛发展&#xff0c;网络安全问题日益凸显&#xff0c;成为社会各界普遍关注的焦点。在这样的背景下&#xff0c;软考网络安全专业应运而生&#xff0c;为培养高素质的网络安全人才提供了有力支撑。本文将对软考网络安全专业进行深入剖析&#xff0c;探讨其在信…

在线 SQL 转 SQLAlchemy:一键生成 Python 数据模型

一款高效的在线 SQL 转 SQLAlchemy 工具&#xff0c;支持自动解析 SQL 语句并生成 Python SQLAlchemy 模型代码&#xff0c;适用于数据库管理、后端开发和 ORM 结构映射。无需手写 SQLAlchemy 模型&#xff0c;一键转换 SQL 结构&#xff0c;提升开发效率&#xff0c;简化数据库…

自定义tiptap插件

本文为开发开源项目的真实开发经历&#xff0c;感兴趣的可以来给我的项目点个star&#xff0c;谢谢啦~ 具体博文介绍&#xff1a; 开源&#xff5c;Documind协同文档&#xff08;接入deepseek-r1、支持实时聊天&#xff09;Documind &#x1f680; 一个支持实时聊天和接入 - 掘…

网络安全需要学多久才能入门?

网络安全是一个复杂且不断发展的领域&#xff0c;想要入行该领域&#xff0c;我们需要付出足够多的时间和精力好好学习相关知识&#xff0c;才可以获得一份不错的工作&#xff0c;那么网络安全需要学多久才能入门?我们通过这篇文章来了解一下。 学习网络安全的入门时间因个人的…

EG82088串口边缘计算网关

EG82088串口边缘计算网关 EG8208是一款专业级8路独立隔离型RS485通讯控制器,通过Modbus及JSON支持、灵活的TCP/IP和UDP切换、内置监控自诊断等特性,广泛应用于工业自动化、楼宇管理等领域,为用户提供卓越的数据采集和设备管理解决方案。 接口类型&#xff1a;8RS485/8DO/1LAN协…

Linux下GCC和C++实现带多组标签的Snowflake SQL查询批量数据导出程序

设计一个基于多个带标签Snowflake SQL语句作为json配置文件的Linux下GCC的C代码程序&#xff0c;实现根据不同的输入参数自动批量地将Snowflake数据库的数据导出为CSV文件到本地目录上&#xff0c;标签加扩展名.csv为导出数据文件名&#xff0c;文件已经存在则覆盖原始文件。需…

Trae AI 辅助修复uniapp 微信小程序的Bug

一、transparent的兼容问题 设计稿&#xff1a; 实际在iphone 6 plu上&#xff1a; 直接让Trae AI修复&#xff1a; 修改后验证通过。 二、v-if分支中子元素根据输入框中内容长度动态添加class样式失效 遇到了个“怪问题”&#xff0c;在其他手机或者开发者工具都正常。也…

conda install 和 pip install 的区别

conda install 和 pip install 是两个常用的包安装命令&#xff0c;但它们在很多方面存在差异。 1. 所属管理系统不同 1.1 conda install conda install 是Anaconda和Miniconda发行版自带的包管理工具 conda 的安装命令。conda 是一个跨平台的开源包管理系统和环境管理系统&…

uni-app App 端分段导出 JSON 数据为文件

在开发过程中&#xff0c;我们经常需要将大量数据导出为 JSON 文件&#xff0c;尤其是在处理长列表或大数据集时。然而&#xff0c;直接将所有数据写入一个文件可能会导致性能问题&#xff0c;尤其是在移动设备上。为了优化性能并提高用户体验&#xff0c;我们可以将数据分段导…

视频推拉流EasyDSS案例分析:互联网直播/点播技术与平台创新应用

随着互联网技术的快速发展&#xff0c;直播/点播平台已成为信息传播和娱乐的重要载体。特别是在电视购物领域&#xff0c;互联网直播/点播平台与技术的应用&#xff0c;不仅为用户带来了全新的购物体验&#xff0c;也为商家提供了更广阔的营销渠道。传统媒体再一次切实感受到了…

MySQL再次基础 向初级工程师迈进

作者&#xff1a;在计算机行业找不到工作的大四失业者 Run run run ! ! ! 1、MySQL概述 1.1数据库相关概念 1.2MySQL数据库 2、SQL 2.1SQL通用语法 SQL语句可以单行或多行书写&#xff0c;以分号结尾。SQL语句可以使用空格/缩进来增强语句的可读性。MySQL数据库的SQL语句不区…

手写一个简易版的tomcat

Tomcat 是一个广泛使用的开源 Servlet 容器&#xff0c;用于运行 Java Web 应用程序。深入理解 Tomcat 的工作原理对于 Java 开发者来说是非常有价值的。本文将带领大家手动实现一个简易版的 Tomcat&#xff0c;通过这个过程&#xff0c;我们可以更清晰地了解 Tomcat 是如何处理…