C++入门之模板基础讲解

 更新时间:2021年11月18日 15:33:15   作者:捕获一只小肚皮  
这篇文章主要为大家介绍了C++入门之模板基础,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

前言

今天博主将要介绍的内容是–模板,他在C++中具有非常重要的位置.至于什么是模板呢?我们请看下面的章节.

引入

我们对交换函数Swap已经非常熟悉了,但是我们经常会遇到这样的一些事,比如,很多不同的数据类型进行交换,那么我们就需要写不同的重载Swap,如下:

#include <iostream>
using namespace std;
void Swap(int& a,int& b){
    int t  = a;
    a = b;
    b = t;
}
void Swap(double& a,double& b){
    double t = a;
    a = b;
    b = t;
}
int main()
{
    int a = 10,b = 20;
    double c = 1.2,d = 3.4;
    Swap(a,b);
    Swap(c,d);
    return 0;
}

可以看到,如果有必要,我们需要交换几种类型的数据,就必须写上几种重载Swap,这就导致非常的繁琐,因为我们对其交换逻辑太熟悉了,只是换了变量类型,那有什么办法可以解决呢?没错,这就是我们今天要讲的模板.

模板

概念:在生活中,博主举一个例子,假设你是一个手办厂家,现在你需要售出各种材料和颜色做的悟空手办,首先你需要的就是悟空的模型,然后按照这个模型使用不同的材料.这个模型就是我们在程序中的模板.

模板种类:

  • 函数模板
  • 类模板

函数模板

函数模板的格式:

template<class T1,class T2,...> 
    return_val function_name (para1,para1,...)
{
}

打省略号的都是形参列表,表示参数量自由,我们现在知道了怎样使用函数模板,那试试写一个Swap模板:

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

按照模板规范,我们写出来了Swap的模板,现在测试一下结果是否正确呢?

image-20211027124124726

发现测试结果完全正确.

然后这里博主有个疑问,就是我们调用Swap时,编译器是执行的上面模板呢?还是执行的通过模板推演出来的函数呢?

答:通过模板推演出来的函数,因为C++提出模板是为了节省程序员的时间,我们所省略的工作,只是编译器替我们完成了.

也就是说,比如我们这样调用:

int main()
{
    int a = 10,b = 20;
    Swap(a,b);
    return 0;
}

那么编译器在底部会推演出一个如下函数,并执行:

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

模板的匹配原则

什么叫做模板的匹配原则呢?

就是说当既有定义出来的明确函数,同时又有模板,那么调用函数时候,执行的是哪一个?以下面为例:

void Swap(int& a,int& b){
    int t  = a;
    a = b;
    b = t;
}
template<class T> 
void Swap (T& a,T& b)
{
    T t = a;
    a = b;
    b = a;
}
int main()
{
    int a = 10,b = 20;
    Swap(a,b);
    return 0;
}

匹配顺序为:

  • 如果有定义出来的函数,且类型完全匹配调用时实参类型,则执行定义出来的函数.
  • 如果定义出来的函数,不符合,则执行模板推演.

也就是说,上面的例子中,Swap调用的是我们定义出来的Swap,而不是模板.

模板的显示调用

上面讲解的模板使用,其实被称做隐式调用,现在,博主介绍一下显示调用.

显示调用格式:

function<Type1,Type2,..>(para1,para1,...);

也就是说,我们明确知道需要使用的什么类型,并且就想告诉编译器,我传给你的是什么类型,然后让编译器推演出该类型的函数.比如下面使用:

int a = 10,b = 20;
char c = 'a',d = 'b';
Swap<int>(a,b);  //告诉编译器我传的是int类型
Swap<char>(c,d);  //告诉编译器我传的是char类型

大家可能会问了,这有什么用呢?既然编译器会根据我们的调用情况进行推演,还进行显示调用不是多此一举吗?大家请看下面的代码:

template<class T> 
void Swap (T& a,T& b)
{
    T t = a;
    a = b;
    b = a;
}
int main()
{
    int a = 10;
    double b = 23.22;
    Swap(a,b);         //这样调用编译器就会报错
    return 0;
}

像上面的调用方式,是不允许的,因为模板中只有一个T,但是我们传了两个类型,编译器根据模板将不知道T应该是啥类型,而解决上面的问题只有两种

  • 一是强制性转换类型,比如Swap(a,(int)b);
  • 二是显示使用模板,比如Swap<int>(a,b);

其次,博主讲解模板的显示调用还有一个目的就是为了引出下面的类模板.

类模板

类模板和函数模板相似,定义框架如下:

template <class T1,class T2,...>
    class class_name
    {
    };

我们对数据结构—栈,应该算比较了解,而对于经常刷力扣的伙伴来说,可能会发现栈不只是用来存储int类型,比如还有ListNode*等,那我们大概写一下其stack模板吧.

template <class T>
class Stack
{
public:
    Stack():data(new T*[10]),top(0),capacity(10) {}
    ~Stack() 
    {
        delete[] data; 
        top = capacity = 0;
    }
    void Push(T& a)
    {}
private:
    T* data;
    int top;
    int capacity;
};

然后我们定义Stack对象,但是对象应该存储的类型是什么呢?如果我们继续用最开始的隐式模板方法,发现完全实现不了,这也就是博主上面为何要讲解模板的显示调用,因为类模板只能通过显示调用实现,例子使用如下:

Stack <char> st1;      //定义一个存储char类型的栈
Stack <int> st2;       //定义一个存储int类型的栈
Stack <double> st3;    //定义一个存储double类型的栈

Stack并不是类,其只是一个模板,Stack <int>等才是类

注意1

类模板只是一个模板,他并不属于类.

注意2

当我们的模板类中的成员函数,在模板中声明,而在模板外定义时,需要加上模板参数列表,如下:

template <class T>
class Stack
{
public:
    void Push(T& a);
    bool empty();
private:
    T* data;
    int top;
    int capacity;
};
template <class T> 
void Stack<T>:: Push(T& a)     //需要加上template <class T> ,且在Stack后面加上<T>
{}
template <class T>   
void Stack<T>:: empty()        //需要加上template <class T> ,且在Stack后面加上<T>
{}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

相关文章

  • C语言关键字auto与register及static专项详解

    C语言关键字auto与register及static专项详解

    这篇文章主要解释了c语言中什么是数据类型,什么是变量,他们的真正含义是什么。分析了属性关键字auto,register和static的用法
    2022-07-07
  • 使用C++的string实现高精度加法运算的实例代码

    使用C++的string实现高精度加法运算的实例代码

    下面小编就为大家带来一篇使用C++的string实现高精度加法运算的实例代码。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • C++利用容器查找重复列功能实现

    C++利用容器查找重复列功能实现

    本文将详细介绍c++容器简介,c++容器的比较 与操作实例,需要了解更多的朋友可以参考下
    2012-11-11
  • C 语言基础教程(我的C之旅开始了)[九]

    C 语言基础教程(我的C之旅开始了)[九]

    C 语言基础教程(我的C之旅开始了)[九]...
    2007-02-02
  • C++11中异常处理机制详解

    C++11中异常处理机制详解

    传统的C语言处理异常的方式有两种:终止程序和返回错误码。在实际中的C语言程序基本都是通过返回错误码的方式来处理错误的,部分情况下使用终止程序来处理比较严重的错误。本文将通过示例和大家聊聊C++11中异常处理机制,需要的可以参考一下
    2022-09-09
  • C/C++中的atan和atan2函数实例用法

    C/C++中的atan和atan2函数实例用法

    在本篇文章里小编给大家分享的是一篇关于C/C++中的atan和atan2函数实例用法相关内容,有兴趣的朋友们可以学习下。
    2020-02-02
  • QT判断两个日期时间的大小

    QT判断两个日期时间的大小

    本文主要介绍了QT判断两个日期时间的大小,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • 带你了解C++的动态内存分配

    带你了解C++的动态内存分配

    今天小编就为大家分享一篇关于关于C++动态分配内存的介绍,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2021-08-08
  • C++ Boost Lockfree超详细讲解使用方法

    C++ Boost Lockfree超详细讲解使用方法

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
    2022-11-11
  • 老生常谈C/C++内存管理

    老生常谈C/C++内存管理

    下面小编就为大家带来一篇老生常谈C/C++内存管理。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05

最新评论