C++-第三章:模板初阶

ops/2025/1/20 4:10:19/

目录

第一节:模板是什么

第二节:函数模板

        2-1.使用场景

       2-2.使用方法

        2-3.模板原理

        2-4.使用细节

第三节:类模板

        3-1.使用场景

        3-2.使用方法

        3-3.类模板中成员函数的声明与定义分离

        3-4.使用细节


第一节:模板是什么

        现实生活中的模具,照着模具可以得到形状相同的模型,然后使用不同颜色的材料就可以得到不同颜色的模型。

        模板也一样,编译器根据模板可以得到大体相似的模型,它们只有细微的区别。模板分为函数模板、类模板,下面一个一个来介绍。

第二节:函数模板

        2-1.使用场景

        函数模板就是可以实例化出函数的模板,对于一些功能相似,但是类型不同的参数的函数有奇效,例如要交换两个数的值,如果两个数都是整型:

void Swap(int& a, int& b) {int tmp = a;a = b;b = tmp;
}

        如果两个数都是浮点型:

void Swap(float& a, float& b) {float tmp = a;a = b;b = tmp;
}

       2-2.使用方法

        对比以上两段代码可以发现,函数功能都是交换两个数,所以将类型 int 替换成 float 即可,除了int和float,还有char、double、自定义类型等类型,全部写出来的话就太多了,既然逻辑一样,那么就可以用一个模板函数来代替这么多不同参数的函数:

template<class T>
void Swap(T& a, T& b) {T tmp = a;a = b;b = tmp;
}

        template标识这是一个模板,而class T就是我们需要给这个模板提供的类型,例如现在需要交换int类型的两个数:

template<class T>
void Swap(T& a, T& b) {T tmp = a;a = b;b = tmp;
}
int main() {int a = 2, b = 3;Swap<int>(a, b);std::cout << "a:" << a << std::endl;std::cout << "b:" << b << std::endl;return 0;
}

  

        就像函数传参一样将 int 传给模板,模板的 T 接收到之后将 T 换成 int 实例化出了一个新的函数。

        如果我又想交换两个 float 类型的数:

int main() {float a = 2.1, b = 3.2;Swap<float>(a, b);std::cout << "a:" << a << std::endl;std::cout << "b:" << b << std::endl;return 0;
}

  

        除了使用<类型>显示传入类型外,函数模板也会自动识别传入参数的类型并实例化相应的函数:

template<class T>
void Swap(T& a, T& b) {T tmp = a;a = b;b = tmp;
}
int main() {int a = 2, b = 3;Swap(a, b);std::cout << "a:" << a << std::endl;std::cout << "b:" << b << std::endl;return 0;
}

  

        2-3.模板原理

        需要注意的是模板实例化出的函数不是同一个函数,即Swap<int>和Swap<float>虽然都使用了模板,但是调用的不是同一个函数,而是编译器在编译阶段利用模板自己写了以下两个函数,和我们自己写的没有区别。

void Swap(int& a, int& b) {int tmp = a;a = b;b = tmp;
}
void Swap(float& a, float& b) {float tmp = a;a = b;b = tmp;
}

        相当于编译器帮助我们写了我们该写的代码。

        2-4.使用细节

        模板函数也有很多使用上的细节,如果有现成的函数与函数模板冲突时,会优先调用现成的函数:

template<class T>
void func(T x) {std::cout << "调用了函数模板:" << x << std::endl;
}void func(int x) {std::cout << "调用了现成函数:" << x << std::endl;
}int main() {int a = 99;func(a);return 0;
}

   

        模板名和现有函数名都是 func,但是会优先调用已经有的函数,而不会实例化一个再调用。

        当参数类型与现成的函数不匹配时,会使用函数模板:

template<class T>
void func(T x) {std::cout << "调用了函数模板:" << x << std::endl;
}void func(int x) {std::cout << "调用了现成函数:" << x << std::endl;
}int main() {float a = 99; // int->floatfunc(a);return 0;
}

   

        

        如果想要强制使用函数模板,可以加上<类型>进行显示实例化:

template<class T>
void func(T x) {std::cout << "调用了函数模板:" << x << std::endl;
}void func(int x) {std::cout << "调用了现成函数:" << x << std::endl;
}int main() {int a = 99;func<int>(a); // 显式实例化return 0;
}

  

第三节:类模板

        3-1.使用场景

        类模板主要用于一些容器,比如vector、queue、map等,其中vector类似于C语言中的数组,C语言的数组的元素可以是char、int等,vector就是对传统数组的封装,为了能够像传统数组一样作用与多种类型,故其使用了类模板。

        3-2.使用方法

        使用方法与函数模板相似:

template<class T>
class A {
public:void PrintVal() {std::cout << _val << std::endl;}T _val;
};

        想要创建一个 _val 为 float 类型的类,只能使用显式实例化:

int main() {A<float> obj;return 0;
}

        3-3.类模板中成员函数的声明与定义分离

        类模板实例化出的类的成员函数也可以进行声明与定义分离,需要标注函数来自哪个类域:

template<class T>
class A {
public:void PrintVal(); // 成员函数声明T _val;
};template<class T> // 成员函数声明定义
void A<T>::PrintVal() {std::cout << _val << std::endl;
}

        3-4.使用细节

        来自同一模板、类型不同的两个对象不属于同一类,例如:

int main() {A<int> a1;A<float> a2;return 0;
}

        虽然a1、a2都是由模板A而来,但却是A实例化出的两个类,这两个类再实例化而来,所以a1、a2不属于同一类。

第四节:下期预告

        下一次将详细介绍string容器,主要是迭代器的实现。


http://www.ppmy.cn/ops/151559.html

相关文章

电机驱动-标准库和HAL库

一、标准库 Motor.c-标准库 #include "stm32f10x.h" // Device header #include "PWM.h"/*** 函 数&#xff1a;直流电机初始化* 参 数&#xff1a;无* 返 回 值&#xff1a;无*/ void Motor_Init(void) {RCC_APB2PeriphClockCmd…

【软件测试】用例篇

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 &#x1f308;个人主页&#xff1a; 南桥几晴秋 &#x1f308;C专栏&#xff1a; 南桥谈C &#x1f308;C语言专栏&#xff1a; C语言学习系…

【网络协议】ACL(访问控制列表)第二部分

概述 在【网络协议】ACL&#xff08;访问控制列表&#xff09;第一部分中&#xff0c;我们介绍了 ACL 的基本概念&#xff0c;讨论了它的工作原理&#xff0c;并以标准 ACL 的配置为结束。第二部分将重点讨论扩展 ACL 以及其他相关的 ACL 概念&#xff0c;接着介绍如何配置扩展…

传统架构下应用部署

2.1传统架构下应用部署 实验目标&#xff1a; 目标为在传统架构下搭建LAMP&#xff08;LinuxApacheMySQL/MariaDBPHP,流行的开源软件组合&#xff09;环境并部署WordPress服务&#xff0c;本次模拟在安装好的openEuler22.03系统虚拟机实现。 节点配置&#xff1a; 虚拟机版本…

微信小程序:跨页面数据修改全攻略

一、引言 在微信小程序开发中&#xff0c;常常会遇到需要在不同页面之间修改数据的情况。比如在商品详情页添加商品到购物车后&#xff0c;购物车页面需要实时更新商品数量和总价&#xff1b;在用户设置页面修改了个人信息&#xff0c;首页的用户信息展示区域也需要同步更新。…

软件测试 —— Selenium(窗口)

软件测试 —— Selenium&#xff08;窗口&#xff09; 多个窗口打开情况current_window_handle、window_handles和switch_to.window示例代码注意事项 窗口大小的设置窗口最大化 maximize_window()窗口最小化 minimize_window()指定窗口全屏 fullscreen_window()手动设置窗口大小…

基于微信小程序的优购电商系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

【CSS】渐变光晕

dom元素 <div id"box" class"glow"></div>css样式 #box { height: 300px;width: 300px;background-image: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 127, color-stop(0%, #CE1A1A), color-stop(100%, #ffffff));background-image:…