c++ 模板的具体化与实例化

2023-11-18

函数模板是C++新增的一种性质,它允许只定义一次函数的实现,即可使用不同类型的参数来调用该函数。这样做可以减小代码的书写的复杂度,同时也便于修改(注:使用模板函数并不会减少最终可执行程序的大小,因为在调用模板函数时,编译器都根据调用时的参数类型进行了相应实例化)。下面来看看函数模板的使用过程:

struct job
{
    char name[20];
    int salary;
};

template <class T> //函数模板声明,通用变量类型为T
void swap(T &a, T &b);

void showJob(const job &a);//打印job内容

using std::cin;
using std::cout;
using std::endl;
void main(void)
{

    int a = 4;
    int b = 5;
    cout<<"Before swap a = "<<a<<" b="<<b<<endl;
    swap(a, b);
    cout<<"After swap a = "<<a<<" b="<<b<<endl;
   
    job jobA = {"coder", 10000};
    job jobB = {"manager", 1000};  
    cout<<"Before swap";
    showJob(jobA);
    showJob(jobB);
    cout<<endl;
    swap(jobA, jobB);
    cout<<"After swap";
    showJob(jobA);
    showJob(jobB);
    cout<<endl;
system("pause");
};

template<class T> //函数模板实现
void swap(T &a, T &b)
{
    T temp;
    temp = a;
    a = b;
    b = temp;
}

void showJob(const job &a)
{
cout<<" "<<a.name<<" = "<<a.salary;
}

 

 

如果在上述job结构互换过程中只想互换salary,而不换其他成员变量值那么怎么办呢?C++中可以通过以下几种方法来解决这一问题。

1>显式具体化
显式具体化也是基于函数模板的,只不过在函数模板的基础上,添加一个专门针对特定类型的、实现方式不同的具体化函数。
template<>void swap<job>(job &a, job &b)
{
     int salary;
     salary = a.salary;
     a.salary = b.salary;
     b.salary = salary;
}

如上所示,该具体化函数的实现与模板并不一致,编译器解析函数调用时会选择最匹配的函数定义。

2>定义同名常规函数
void swap(job &a, job &b)
{
     int salary;
     salary = a.salary;
     a.salary = b.salary;
     b.salary = salary;
}
由于编译器在重载解析时,会选择最匹配函数定义,所以在调用swap(jobA, jobB)时,编译器会选择void swap(job &a, job &b)函数定义,而屏蔽了模板函数。

 

 

同时,模板函数也可以重载,其操作与常规函数一致。
template <class T> void swap(T &a, T &b);

template <class T> void swap(T &a, T &b, T &c);

template <typename T> void swap(T &a, T &b)
{
    T temp;
    temp = a;
    a = b;
    b = temp;
}

template <typename T> void swap(T &a, T &b, T &c)
{
    T temp;
    temp = a;
    a = b;
    b = c;
    c = temp;
}

 

上面主要说的是函数模板的具体化,下面说下模板实例化。

函数模板:
#define MAXNAME 128
struct job
{
char name[MAXNAME]:
int salary;
};

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

template void swap<int>(int &a, int & b);  //显式实例化,只需声明

template<> void swap<job>(job &a, job &b)   //显式具体化(上面已经讲过,注意与实例化区分开,必须有定义)
{
  int salary:
  salary = a.salary:
  a.salary = b.salary;
  b.salary = salary;
};//explicite specialization.

类模板:
template <class T>
class Arrary
{
private:
  T* ar;
  int l;
...
};//template class declaration.

template class Array<int>;   //explicit instantiation. 显式实例化

template<> class Array<job>
{
private:
  job* ar;
  int l;
};//expicit specialization.   显式具体化,类定义体可以不同于类模板Array

相应的,隐式实例化指的是:在使用模板之前,编译器不生成模板的声明和定义实例。只有当使用模板时,编译器才根据模板定义生成相应类型的实例。如:
int i=0, j=1;
swap(i, j);  //编译器根据参数i,j的类型隐式地生成swap<int>(int &a, int &b)的函数定义。
Array<int> arVal;//编译器根据类型参数隐式地生成Array<int>类声明和类函数定义。

显式实例化:
当显式实例化模板时,在使用模板之前,编译器根据显式实例化指定的类型生成模板实例。如前面显示实例化(explicit instantiation)模板函数和模板类。其格式为:
template typename function<typename>(argulist);
template class classname<typename>;
显式实例化只需声明,不需要重新定义。编译器根据模板实现实例声明和实例定义。

显示具体化:
对于某些特殊类型,可能不适合模板实现,需要重新定义实现,此时可以使用显示具体化(explicite specialization)。显示实例化需重新定义。格式为:
template<> typename function<typename>(argu_list){...};
template<> class classname<typename>{...};

 

 
综上:
template<> void swap<job>(job &a, job &b) {……};是函数模板的显式具体化,意思是job类型不适用于函数模板swap的定义,因此通过这个显式具体化重新定义;也可简写作template<> void swap(job &a, job &b);
template void swap<job>(job &a, job &b);是函数模板的一个显式实例化,只需声明,编译器遇到这种显式实例化,会根据原模板的定义及该声明直接生成一个实例函数,该函数仅接受job型。否则编译器遇到模板的使用时才会隐式的生成相应的实例函数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++ 模板的具体化与实例化 的相关文章

  • 项目在was 7.0上部署问题解决方案

    年前 在做项目的时候 遇到客户要求应用服务器采用WebSphere服务器 之前从来没有接触过该类服务器 所以项目在架构部署上遇到了很多问题 现在给自己做个笔记 记录一下在websphere应用上遇到的问题 为以后做参考 同时 给有遇到此问题

随机推荐

  • 谈GPT-2(附大量网址)

    文章目录 前言 关于GPT 2 各个版本的GTP 2 中文版GTP 2 语料链接 15亿参数版GPT 2 OpenGPT 2 前言 GPT 2这个名字不知有多少人知道 但有很多人应该都知道埃隆 马斯克的OpenAI吧 OpenAI 由诸多硅
  • Python时间模块之calendar模块

    目录 简介 calendar month isleap calendar leapdays monthcalendar monthrange timegm 总结 简介 在项目开发中做功能经常会用到关于时间的操作 比如会员过期的定时任务 一些
  • 计算机视觉需要学什么?CV知识点

    最近有人问计算机视觉需要学什么 我自己本身是通过自学然后找到了计算机视觉相关的工作 这里我分享一下自己的当初掌握的知识点 希望能帮助到你 以下内容仅供参考 计算机视觉需要学什么 学习计算机视觉需要具备的知识储备有 1 图像处理的知识 图像处
  • 记录一次rabbitmq ConfirmCallback不生效的问题

    记录一次rabbitmq回调函数不生效的问题 application yml里是否存在 springboot版本的问题 改为2 1 7 RELEASE即可 以上都未生效的话 检查一下是否自己写了连接rabbitmq的bean 在里面加上下面
  • Unity 3D中的帧动画播放

    帧动画 Frame By Frame 的原理 链接 项目实例资源 关键是连续的关键帧分解动作 也就是在时间轴的每帧上逐帧绘制不同的内容 使其连续播放而成动画 虽然每一帧都不一样 处理的信息量大 但是 帧动画具有非常大的灵活性 几乎可以表现任
  • C/C++之内存四区

    程序运行时 将内存大致分为四个区域 代码区 存放函数体的二进制代码 由操作系统进行管理的 全局区 存放 全局变量和 静态变量以及 常量 栈区 由编译器自动分配释放 存放函数的参数值 局部变量等 堆区 由程序员分配和释放 若程序员不释放 程序
  • numpy——mgrid

    x1 x2 np mgrid x1min x1max num1j x2min x2max num2j x1返回的是x1min到x1max间均匀分成num1个数 进行横向扩展为方阵 x2返回的是x2min到x2max间均匀分成num2个数 进
  • 企业级数据单表全量增量抽取数据模型(Kettle版)

    最近在使用Kettle进行ETL的工作 现在总结一下 需求是将MYSQL中的表数据增量备份到HIVE仓库中 第一次是全量 我只想给大伙来点实用的 避免大家踩坑 Kettle是一个基于图形化的ETL工具 也可以用于集成各种作业 比如Sqoop
  • Spring Boot之自定义JSON转换器

    JSON是前后端数据交互最流行的格式 在目前的项目开发中 常见的JSON的转换器有三种 json lib由于自身的缺陷基本不用 最广泛的还是Jackson Jackson 在springboot中默认添加了jackson databind作
  • 使用go语言整合gin,驱动bartender打印标签程序

    可以用来当中间件 项目地址 github GitHub wjdsg0327 printer barTender 使用go语言整合gin驱动bartender打印标签 gitee printer barTender 使用go整合gin驱动ba
  • [kubernetes]step3-kubeadm更新证书有效期

    kubeadm更新kubernetes集群证书 接着上面阿里云上的kubernetes集群 一步步搭建服务 因为kubernetes要上云测试了 不想到时候突然因为证书导致服务挂掉 挨批 就把证书更新一下 感觉10年差不多了 查看证书过期时
  • Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore

    Java并发编程 CountDownLatch CyclicBarrier和 Semaphore 2016 10 07 分类 基础技术 7 条评论 标签 并发 分享到 0 原文出处 海子 在java 1 5中 提供了一些非常有用的辅助类来帮
  • linux源码安装git 教程 ,设置远程库,客户端访问完整版

    1 linux 在 github 下载 git 安装包 然后解压 wget https github com git git archive v2 21 0 tar gz tar zxvf git v2 21 0 tar gz 2 安装gi
  • C++的文件操作open与close

    先看一下相应的打开文件的不同参数的作用 C open 打开文件 含打开模式一览表 打开模式可以用多个 但符号是 不是 注意啦 比如 ios in ios binary表示用二进制模式 以读取的方式打开文件 ios out ios binar
  • 3. 类指针与智能指针

    3 类指针与智能指针 本篇主要解答以下问题 类的对象与类指针的区别 为什么要用智能指针 unique ptr 和 shared ptr 3 1 类对象与类指针 实例化一个类的时候 有两种方式 一是创建对象 二是创建指针 以2 1中的stud
  • 页表长度和页表大小_OS——关于页面大小与页表项的问题

    一 采用分页管理方式时 操作系统将进程划分成若干个页面 将内存划分为若干个内存块 or页 页面和内存块大小一致并且一一对应 但是由于进程划分页面时 最后一个页面大小可能小于内存块大小 导致存放的最后一个内存块存在内部碎片 成为页内碎片 为了
  • 数据库中视图、索引、存储过程的作用

    视图可以被看成是虚拟表或存储查询 可通过视图访问的数据不作为独特的对象存储在数据库内 数据库内存储的是 SELECT 语句 SELECT 语句的结果集构成视图所返回的虚拟表 用户可以用引用表时所使用的方法 在 Transact SQL 语句
  • 内置对象Session与HttpSession是同一个东西吗?

    本质上是 在jsp中session是个内置对象 而在servlet中想使用session就要先得到session 方法如下 HttpSession session request getSession 在jsp中或是在servlet中ses
  • 原动力×云原生正发声 降本增效大讲堂

    原动力 云原生正发声 降本增效大讲堂课程活动链接 原动力 云原生正发声 降本增效大讲堂 提升IT资源利用率 实现降本增效 已经成为企业关注重点 2021 年 CNCF FinOps Kubernetes Report 指出 迁移至 Kube
  • c++ 模板的具体化与实例化

    函数模板是C 新增的一种性质 它允许只定义一次函数的实现 即可使用不同类型的参数来调用该函数 这样做可以减小代码的书写的复杂度 同时也便于修改 注 使用模板函数并不会减少最终可执行程序的大小 因为在调用模板函数时 编译器都根据调用时的参数类