c++:模板

server/2024/11/19 5:45:45/

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;
}
void Swap(char& a, char& b) //字符型
{
    char tmp = a;
    a = b;
    b = tmp;
}

代码的关键部分非常相似,代码很冗余,使用泛型编程可以很好的解决这个问题 

 template<typename T1>  //这是一个函数模板,可以完成上面三个函数的功能 
void Swap(T1& a, T1& b)
{
    T tmp = a;
    a = b;
    b = tmp;
}

泛型编程就像是一个模子,让编译器根据不同类型,生成不同的代码 ,从而实现对应的功能                

 2.函数模板

1.函数模板概念 

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

函数模板是一种用于生成函数的工具,通过模板定义可以创建适用于多种数据类型的函数

2.函数模板格式 

template<typename T1, typename T2 ......> 

返回值类型   函数名(参数列表)

{

    //代码块

}

 例如上面交换两个变量的值的例子

template<typename T1>

void Swap(T1& a, T1& b)
{
    T tmp = a;
    a = b;
    b = tmp;

typename是用来定义模板参数关键字,也可以使用class 

3.函数模板原理 

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。 所以其实模板就是将本来应该我们做的重复的事情交给了编译器 

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应 类型的函数以供调用。

4.函数模板的实例化 

用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化显式实例化 

1.隐式实例化:让编译器根据实参推演模板参数的实际类型

template<class T>
T Add(const T& a, const T& b)
{
    return a + b;
}
int main()
{
    int a1 = 10;
    int a2 = 5;
    float b1 = 10.5;
    float b2 = 4.0;

    Add(a1, a2);
    Add(b1, b2);

    Add(a1, b1);  //编译器无法确定T是整形还是浮点型而报错
    Add(a1, (int)b1);  //可以将b1强制转换成int类型
    return 0;
}

2.显式实例化:在函数名后的<>中指定模板参数的实际类型 

int main(void)
{
    int a = 10;
    double b = 20.0;
    // 显式实例化
    Add<int>(a, b);  //显示为int类型
    return 0;

 5.模板函数匹配原则

1.一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数 

//专门处理int的加法函数,非模板函数
int Add(int left, int right)
{
    return left + right;
}


// 通用加法函数,函数模板
template<class T>
T Add(T left, T right)
{
    return left + right;
}


void Test()
{
    Add(1, 2);         // 与非模板函数匹配,编译器不需要特化
    Add<int>(1, 2);  // 调用编译器特化的Add版本

就是说,如果我们已经定义了一个函数模板,又有一个非模板函数,在调用一个函数时,非模板函数与模板函数都适配,优先选择非模板函数,如果模板可以产生一个具有更好匹配的函数, 那么将选择模板函数

显示实例化调用,则调用模板函数 (模板函数是指编译器通过函数模板生成的一个函数)

// 专门处理int的加法函数
int Add(int left, int right)
{
    return left + right;
}

// 通用加法函数
template<class T1, class T2>
T1 Add(T1 left, T2 right)
{
    return left + right;
}
void Test()
{
    Add(1, 2);        // 与非函数模板类型完全匹配,不需要函数模板实例化
    Add(1, 2.0);    // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数
}

还需要注意的一点是: 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

3.类模板 

1.类模板的定义格式 

template<class T1, class T2, ..., class Tn>
class 类模板名
{
    // 类内成员定义
}; 

例如下面这个例子: 

// 类模版
template<typename T>
class Stack
{
public:
    Stack(size_t capacity = 4)
    {
        _array = new T[capacity];
        _capacity = capacity;
        _size = 0;
    }
    void Push(const T& data);
private:
    T* _array;
    size_t _capacity;
    size_t _size;
};

// 模版不建议声明和定义分离到两个文件.h 和.cpp会出现链接错误
template<class T>
void Stack<T>::Push(const T& data)
{
    // 扩容
    _array[_size] = data;
    ++_size;
}


int main()
{
    Stack<int> st1;            // int
    Stack<double> st2;     // double
    return 0;
}

2.类模板的实例化 

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>然后将实例化的 类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类

// Stack是类名,Stack<int>才是类型

Stack<int>  st1;           // int

Stack<double>  st2;    // double


http://www.ppmy.cn/server/143096.html

相关文章

【AIGC】如何使用高价值提示词Prompt提升ChatGPT响应质量

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | 提示词Prompt应用实例 文章目录 &#x1f4af;前言&#x1f4af;提示词英文模板&#x1f4af;提示词中文解析1. 明确需求2. 建议额外角色3. 角色确认与修改4. 逐步完善提示5. 确定参考资料6. 生成和优化提示7. 生成最终响…

MySQL的编程语言

一、MySQL基础 使用系统的全局变量@@VERSION查看当前使用的MySQL的版本信息,SQL语句如下: select @@version; 将局部变量varl声明为char的类型,长度值为10,并为其赋值为“程菲” begin declare var1 char(10); set @var1="程菲"; end 通过局部变量查看d_eams数…

Flutter-左侧导航栏跟随窗口的宽变化

前言 现在有一个需求&#xff1a;左侧导航栏跟随窗口的宽度变化而变化 当宽度>1000时&#xff0c;左侧导航栏全部展示&#xff0c;1000>宽度>500时,左侧导航栏只展示图标&#xff0c;500>宽度时&#xff0c;左侧导航栏消失&#xff0c;顶部出现菜单选择图标&…

【ORACLE战报】2024年10月OCP考试战报

原创 厦门微思网络 微思 | 新班预告&#xff1a; 所有的收获都是默默耕耘的成果 2024.10月【最新考试成绩出炉】 来吧&#xff0c;展示 &#xff08;以下为部分学员成绩单&#xff09; &#xff08;部分学员证书&#xff09; 往期考试战报回顾&#xff1a; 【ORACLE战报】…

解析“ChatGPT网络错误”:从网络专线到IP地址的根源与解决方案

在日常使用 ChatGPT 或其他在线服务时&#xff0c;偶尔会遇到“网络错误”的提示&#xff0c;尤其是在请求响应时间较长或出现连接中断的情况下。这种错误常常让用户感到困扰&#xff0c;但实际上&#xff0c;网络错误的发生并不总是因为服务端出现问题&#xff0c;很多时候&am…

FFmpeg 4.3 音视频-多路H265监控录放C++开发十三.2:avpacket中包含多个 NALU如何解析头部分析

前提&#xff1a; 注意的是&#xff1a;我们这里是从avframe转换成avpacket 后&#xff0c;从avpacket中查看NALU。 在实际开发中&#xff0c;我们有可能是从摄像头中拿到 RGB 或者 PCM&#xff0c;然后将pcm打包成avframe&#xff0c;然后将avframe转换成avpacket&#xff0…

【计算机网络】TCP协议特点1

TCP/IP协议头 TCP/IP族是一组网络通信协议的集合&#xff0c;一个分层、多协议的通信体系&#xff0c;它是互联网的基础通信协议。这个协议族定义了电子设备如何连入互联网&#xff0c;以及数据如何在它们之间传输。TCP/IP 协议族通常被分为四层&#xff0c;从下到上分别是数据…

移门缓冲支架:减少噪音,提升生活质量

移门缓冲支架不仅是一个简单的五金配件&#xff0c;更是提升家居生活质量的有效工具。通过减少门关闭时的噪音&#xff0c;移门缓冲支架能够创造一个安静、舒适的生活环境。以下是移门缓冲支架在减少噪音、提升生活质量方面的详细解析&#xff1a; 1. 显著降低关门噪音问题&…