boxmoe_header_banner_img

糖画99

文章导读

模版初阶


avatar
mizuki 2026年5月31日 5

前言

C++与C语言之间其中不同的一点就是C++可以启用模版,为程序员省下了许多近乎重复的代码书写,这篇文章将为你介绍模版初阶的知识,让你能使用基本的模版

1.模版类型

  • 1.1 模版意义

模版是一种泛式编程,是用来编写与类型无关的通用代码

  • 1.2 模版类型

分为模版函数和类模版

2.函数模版

  • 2.1 格式

这里先写出一个例子,我们再进行解析:

template<class T>
T Add(T a, T b)
{
   return a + b;
}

可以注意到这是一个加法的函数模版,这里的template<class T>,class是类的一个泛称,T则代表的是具体的类型,可以是int,double,float…….而在template下必须接上一个函数声明或定义,在此函数中,T就代表了返回的类型,a和b的类型

  • 2.2 实例化

对于函数模版来说,分为隐式实例化和显示实例化

1.隐式实例化:

template<class T>
T Add(T a, T b)
{
   return a + b;
}

int r = add(10, 20);

这里直接填入两个整数,让编译器自己分析参数的类型,从而生成对应的函数,这就是隐式实例化

2.显示实例化:

template<class T>
T Add(T a, T b)
{
   return a + b;
}

int r = add<int>(10, 20);

这里我们可以注意到我们在函数名后加上了<int>,这就是在告诉编译器这里的T类型是int,编译器就会生成对应的int类型的Add函数,对于一些函数来说,编译器无法进行自我识别,那就要我们写显示实例化

  • 2.3 模版函数和函数重载

在上面几行我们说到了有些函数编译器无法进行自我识别,我们就需要写显示实例化,但这其实是比较麻烦的,更方便的方法是我们直接再写一个重载函数就可以了,这里给出一个例子:

template<class T>
T Add(T a, T b)
{
   return a + b;
}

int Add(int* a, int* b)
{
   return *a + *b;
}

int main()
{
    int a = 10;
    int b = 20;
    int r = Add(&a, &b);
    return 0;
}

你可以去试一试,对于传地址函数模版是无法识别的,所以这里我们直接写一个重载函数就可以了,并且对于模版函数来说,编译器会优先选择已经存在的重载函数,就算模版函数可以成功识别,目的是为了节省编译时间

3.类模版

  • 3.1 格式

这里先写出一个例子,我们再进行解析:

template<class T>
class list
{
   private:
   T _val;
   list* _next;
   list* _prev;
}

这里给出的是链表的例子,与函数模版相同,T是一个类型,而list中_val的类型就是T,其他的与函数模版基本相同,不做过多描述

  • 3.2 实例化

要注意的是,类模版只能显示实例化,没有隐式实例化,这里给出一个例子:

template<class T>
class list
{
   private:
   T _val;
   list* _next;
   list* _prev;
}

list<int> v1;

这里我们可以注意到,v1对象的创建是必须要用显示实例化的

4.模版的特点

  • 4.1 声明与定义分离问题

一般来说,模版的声明和定义分离在不同的两个.h和.cpp文件中会方式连接错误,编译器无法寻找到对应的定义,从而报错

但是,如果真的想将声明和定义分离在不同的不同的两个.h和.cpp文件中,可以采取显示实例化的方式,例子如下:

// ===== math.h =====
template <typename T>
T add(T a, T b);

// ===== math.cpp =====
template <typename T>
T add(T a, T b) {
    return a + b;
}

// 显式实例化:只生成这几个版本的代码
template int add<int>(int, int);
template double add<double>(double, double);

// ===== main.cpp =====
#include "math.h"
int main() {
    int x = add(1, 2);        // ✅ 链接到 math.cpp 生成的 add<int>
    double y = add(1.5, 2.5); // ✅ 链接到 add<double>
    // float z = add(1.0f, 2.0f); // ❌ 链接错误!未实例化 float 版本
}

虽然显示实例化有用,但是很不推荐,还不如正常写函数

  • 4.2 按需实例化

对于类模版来说,其中可能会写很多的成员函数,但是只要不是有特别大的错误,在这个函数被使用之前,很大可能都不会报错,这就叫做按需实例化

因此,当我们写完一个函数的时候一定要去调试一下,以免今后发生难以挽回的错误

总结

模版在今后会非常频繁的进行使用,像是vector,list,stack的模拟实现等等都会使用,所以一定要打好基础



评论(0)

查看评论列表

暂无评论


发表评论

表情 颜文字

插入代码
小园得志