小工具知识网

当前位置: 首页 > 行业知识 > 【爱上C++】函数模板 (1)

行业知识

【爱上C++】函数模板 (1)

2026-11-03 07:02:48 来源:互联网转载

目录

  • 一 泛型编程
    • 1.定义
    • 2. 引入
    • 二 函数模板
      • 1. 函数模板的概念
      • 2. 函数模板的格式
      • 3.函数模板的原理
      • 4.函数模板的实例化
      • 5.显式实例化
      • 6.模板参数的匹配原则
      • 三 类模板
        • 1.类模板的定义格式
        • 2.类模板的实例化

          一 泛型编程

          1.定义

          泛型编程(Generic Programming)是一种编程范式,它旨在编写与数据类型无关的代码。通过这种方式,程序员可以编写出灵活且可重用的代码,这些代码可以对不同类型的数据进行操作,而无需为每种数据类型编写特定的代码。泛型编程主要依赖于模板(Templates)来实现,模板是一种允许程序员在一种类型不确定的情况下,编写通用的代码。

          2. 引入

          C语言中想要实现两个数进行交换可以用 异或,或者用临时变量tmp。

          比如我们想要交换a,b的值,可以用一个Swap函数

          void Swap(int *a,int *b){//用指针的方法int tmp=*a;*a=*b;*b=tmp;}void Swap1(int& a,int &b){//用引用的方法int tmp=a;a=b;b=tmp;}int main(){int a=0,b=1;Swap(&a,&b);return 0;}

          但是如果我又想要交换两个double类型的变量,怎么办?再写一个double* 的Swap?那我又想要交换char类型的呢?是不是还要写,这样是不是很麻烦。哎!我们前面学了函数重载,但如果再有一种类型是不是还要再写一遍?

          使用函数重载虽然可以实现,但是有一下几个不好的地方:

          1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函

            数

          2. 代码的可维护性比较低,一个出错可能所有的重载均出错

            那能否告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码呢?

          如果在C++中,也能够存在这样一个模具,通过给这个模具中填充不同材料(类型),来获得不同材料的铸件

          (即生成具体类型的代码),那将会节省许多头发。巧的是前人早已将树栽好,我们只需在此乘凉。

          泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。

          这时 函数模板就派上用场了。

          二 函数模板

          1. 函数模板的概念

          函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定

          类型版本。

          2. 函数模板的格式

          template

          即:返回值类型 函数名(参数列表){}

          例如:

          template void Swap(T& left,T& right)//注意right不要写错啦,刚刚就写错了{T tmp=left;left=right;right=tmp;}int main(){int a=1,b=2;double c=3.0,d=4.0;char e='x',f='y';Swap(a, b);Swap(c, d);Swap(e, f);coutreturn left+right}int main(){int a=1,b=0;double c=1.0,b=2.0;Add(a,b);Add(c,d);return 0;}int a = 10;double b = 20.13;cout return left + right;}// 函数模板templatereturn left + right;}int main(){// 匹配调用原则:// 1、合适匹配的情况下,有现成的就吃现成// 2、没有就将就吃// 3、有更合适就吃更合适的,哪怕要自己现做coutreturn new T[n];}int main(){//funcreturn left + right;}// 通用加法函数templatereturn left + right;}void Test(){Add(1, 2); // 与非函数模板类型完全匹配,不需要函数模板实例化Add(1, 2.0); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数}    int temp = a;    a = b;    b = temp;}// 模板函数不支持自动类型转换template     T temp = a;    a = b;    b = temp;}int main() {    int x = 5;    double y = 3.14;    cout public:Stack(int capacity = 4) : _top(0) , _capacity(capacity) {_arr = new int[capacity];}~Stack() {delete[] _arr;_arr = nullptr;_capacity = _top = 0;}private:int* _arr;int _top;int _capacity;};Stack st1;//我们想存int数据Stack st2;//我们想存double数据return 0;}// 类内成员定义};public:Stack(T capacity = 4): _top(0), _capacity(capacity) {_arr = new T[capacity];}~Stack() {delete[] _arr;_arr = nullptr;_capacity = _top = 0;}private:T* _arr;int _top;int _capacity;};int main(void){Stack st1;   // 存储intStack st2;   // 存储doublereturn 0;}public://构造函数 (函数名和类名相同,不是类型名)  不写Stackcout //...}private:T* _a;int _top;int _capacity;};//声明和定义分离的话要这样写(也不能放到两个文件,只能放到一个文件里,至于为何模板进阶的时候会讲)//定义templatecout  // 类模板都是显示实例化Stack

上一篇:服务器的cpu怎么监控?

下一篇:怎么让流量飞起?