每日一个C++知识点|模板

什么是模板

C++ 是一门多范式的编程语言,除了面向对象的特点之外,还具备泛型编程的特点,其中模板是泛型编程的核心工具

模板是一份与类型无关的通用代码,编译器会根据你传入的类型,自动推导和生成对应类型的具体代码,这个过程叫 "模板实例化",其中模板包括函数模板类模板

函数模板

如果不使用函数模板,实现两个值交换的函数,会根据传入参数的数据类型不同会有以下几种情况:

cpp 复制代码
#include <iostream>
#include <string>  
using namespace std; 

void Swap(int &a, int &b) // 交换两个int型变量的值。
{
    int tmp = a;
    a = b;  
    b = tmp; 
}

void Swap(double& a, double& b) // 交换两个double型变量的值。
{
    double tmp = a;
    a = b; 
    b = tmp; 
}

void Swap(string& a, string& b) // 交换两个string型变量的值。
{
    string tmp = a;
    a = b; 
    b = tmp; 
}

由上述代码所示,对每一种数据类型的交换,明明是函数逻辑相同,但都要重复写一遍,这种代码方式明显是不高效的,如果用函数模板的方法应该怎么写呢?下面让我们来了解以下函数模板

函数模板是用于实现通用函数,避免因为参数数据类型不同而重复写相同逻辑的代码

基础语法

函数模板的基本使用方法如下

cpp 复制代码
template <typename T>  
返回值类型 函数名(参数列表) {
    // 函数逻辑(用T表示任意类型)
}

其中template是模板关键字,用于声明接下来的代码是一个模板,typename是类型参数的声明符,用于声明后面的标识符是一个 "类型参数",T是你自定义的类型参数名,是一个 "类型占位符",代表任意数据类型

下面我们用参数模板的方法来简化上述交换函数的代码

cpp 复制代码
template <typename T>  
void Swap(T& a, T& b) { 
    T tmp = a; 
    a = b;
    b = tmp;
}

使用函数模板,短短几行代码,就可以实现上述三个不同数据类型的参数的交换函数,这就是使用模板函数带来的价值

多个类型参数的情况

上述是单个类型的参数的情况,交换的都是两个相同类型的函数,如果要交换的是两个不同类型的参数应该怎么做呢?可以使用多个类型参数的情况的函数模板,下面用代码进行举例:

cpp 复制代码
// 两个类型参数:T1和T2
template <typename T1, typename T2>
void printPair(T1 a, T2 b) {
    cout << a << " " << b << endl;
}

// 使用时,T1=int,T2=string
printPair(10, "hello");
// T1=double,T2=bool
printPair(3.14, true);

通过以上代码,我们也可以实现传递两个不同类型参数的函数模板,总之,函数模板可以极大简化我们的代码,不需因为参数类型的不同而重复多写函数逻辑相同的代码,大大提高了代码的复用

类模板

模板除了函数模板之外还有类模板,函数模板是通用函数,那么类模板就是通用类,当你给类模板指定不同的数据类型时,编译器会自动生成对应类型的具体类,这个过程就叫做类模板实例化。函数模板和类模板的区别就是函数模板可以自动推导类型,类模板必须显式指定类型,下面是它的基础用法:

cpp 复制代码
// 模板参数声明
template <class T> 
class 类模板名 {
private:
    // 成员变量可以使用类型参数T
    T m_data;
public:
    // 构造函数、成员函数的参数/返回值也可以使用T
    类模板名(T data) : m_data(data) {}
    T getData(); // 成员函数声明
};

// 类模板的成员函数在类外定义时,需要重新声明模板参数
template <class T>  // 第二处修改:typename → class
T 类模板名<T>::getData() {
    return m_data;
}

以上就是类模板的基础用法,template类模板的声明的关键字,class为模板类型参数声明符,声明后面的标识符T是一个类型参数,T是自定义的模板类型参数名,代表任意数据类型的"占位符",下面用具体的代码进行举例说明:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

// 类模板:通用图形类(T表示尺寸的数据类型,如int、double)
template <typename T>
class Shape {
private:
    string m_name;  // 图形名称(如"圆形"、"正方形")
    T m_size;       // 图形的尺寸(T为类型参数:圆的半径/正方形的边长,类型可以是int/double)
public:
    // 构造函数:初始化图形名称和尺寸
    Shape(string name, T size) : m_name(name), m_size(size) {}

    // 成员函数:修改图形的尺寸
    void setSize(T size) {
        m_size = size;
    }

    // 成员函数:获取图形的尺寸
    T getSize() {
        return m_size;
    }

    // 成员函数:显示图形的信息(简单的输出功能)
    void showInfo() {
        cout << "图形:" << m_name << ",尺寸(半径/边长):" << m_size << endl;
    }
};

上述代码中,用模板类型 T 表示图形的尺寸数据类型

在代码中函数模板和类模板其中一个显著的区别是T函数模板中充当参数的类型,在类模板中充当类的成员变量和成员函数的类型,同时,类模板必须显式指定类型,函数模板可自动推导类型,这是二者最直观的区别

标准模板库STL

STL 是C++标准库的核心部分,它完全基于模板实现,为开发者提供了现成的、通用的容器、算法、迭代器等组件,是模板泛型编程的终极实战成果,由于篇幅所限,这里就不展开讲,感兴趣的话可以观看往期的内容《每日一个C++知识点|STL基础》,那里有详细说明

总结

  1. C++ 模板分为函数模板和类模板,核心是用类型参数T实现代码的通用性,让一份代码适配不同类型
  2. 模板的关键是编译期实例化:编译器根据指定的具体类型,生成对应版本的函数或类
  3. 函数模板可自动推导类型,类模板必须显式指定类型
  4. STL是完全基于模板实现的C++标准库

本文到此结束,如果文章对你有用的话欢迎点赞收藏加关注哦~

相关推荐
xiaolang_8616_wjl2 小时前
c++超级细致的基本框架
开发语言·数据结构·c++·算法
Joy-鬼魅3 小时前
Win10x64系统VS2022使用CreateFileMapping返回无效句柄
c++·createfilemap·vc·getlasterror
冷崖3 小时前
排序--基数排序
c++·算法
淼淼7633 小时前
Qt调度 程序
开发语言·c++·windows·qt
暗然而日章4 小时前
C++基础:Stanford CS106L学习笔记 13 特殊成员函数(SMFs)
c++·笔记·学习
云泽8084 小时前
STL容器性能探秘:stack、queue、deque的实现与CPU缓存命中率优化
java·c++·缓存
J ..4 小时前
C++ Lambda 表达式完全指南
c++
Qt程序员4 小时前
从 C++11 到 C++23:枚举的原理升级与实践
c++·c++23
CC.GG4 小时前
【C++】红黑树
java·开发语言·c++