当前位置: 首页 > news >正文

模板初阶

一、函数模板

函数模板概念:

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

函数模板格式:

template <typename X1,typename X2…………typename Xn>  //typename可以用class代替

函数模板原理:

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

template <typename t>void swap(t& x, t& y)
{t a = x;x = y;y = a;
}

   上面实现的swap函数就是用了函数模板,当我们调用函数时,编译器会自动推导形参的类型,然后再生成具体函数。

 

 函数模板实例化

  函数模板实例化分为隐式实例化显示实例化

隐式实例化:

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

template <typename t>void Swap(t& x, t& y)
{t a = x;x = y;y = a;
}int main() 
{int a = 1, b = 2;double c = 3.1, d = 4.2;Swap(a, b);Swap(c, d);return 0;
}

  当然还会产生这样的问题:

Swap(a,c);

  因为模板列表中只有一个t,这样写的话就不清楚t是int还是double类型从而报错。要处理的话可以选择类型强制转化或者模板显式实例化

    Swap((double)a,c);//类型强制转化

  值得注意的是,类型强制转化的过程中会产生临时对象,而临时对象具有常性,故函数形参必须不可修改。 

  因为Swap函数的特殊性实参不能直接强转类型,故下面暂时替换成add函数。

template <typename t>//const引用接收临时对象
t add(const t& x, const t& y)
{return x+y;
}int main() 
{int a = 1, b = 2;double c = 3.1, d = 4.2;add((double)a,c);//类型强制转化产生临时对象,临时对象具有常性return 0;
}
 显示实例化

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

Swap<int>(a,c);//将函数参数显示化为int类型

  当然如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。

 std::string s="fsad";Swap<int>(s,c);//s为string类型无法隐式类型转化成int类型,编译报错

 模板参数的匹配原则

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

   2. 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而 不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板

int Swap(int& x, int& y)
{int a = x;x = y;y = a;return 0;
}template <typename t>
void Swap( t& x,  t& y)
{t a = x;x = y;y = a;
}int main() 
{int a = 1, b = 2;double c = 3.1, d = 4.2;Swap(a, b);//a,b均为int类型,不需要调用模板Swap(c, d);//没有符合的函数,调用模板return 0;
}

   3. 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换 

二、类模板

类模板的定义格式

template<class T1, class T2, ..., class Tn> 
class 类模板名
{// 类内成员定义
}; 
 类模板实例化:
template <typename t>
class TN
{
public:TN(t y):x(y){}
private:t x;//…………
};
//显示实例化TN<double>
template class TN<double>;int main() 
{TN<int> a1(10);//隐式实现,<int>只是指出10为int类型,并没有直接生成具体的类TN<double> a2(20) ;//显示实例化return 0;
}

  上面类模板隐式实例化中:TN是类名,TN<类型名> 才是类型

  类模板显式实例化与隐式实例化的不同一点就是显式实例化还需要一个专门的语法

template class 类名<实例化的类型>;

注意事项:

  模版不建议声明和定义分离到两个文件.h 和.cpp,会出现链接错误。模板不是直接编译成可执行代码的实体,而是代码生成的蓝图。编译器只有在同时看到模板的完整定义具体实例化类型时,才能生成对应的具体代码。

   当进行声明与定义分离时,编译器会因为声明和显式实例化不完整从而最终链接时,会出现 “未定义的引用” 错误

  

http://www.dtcms.com/a/306535.html

相关文章:

  • C++ 中 NULL 与 nullptr 有什么区别?
  • Redis 中 key 的过期策略 和 定时器的两种实现方式
  • 基于逻辑回归、随机森林、梯度提升树、XGBoost的广告点击预测模型的研究实现
  • 超宽带测距+测角+无线通信一体化跟随模组:机械狗、无人车、无人机等跟随
  • Dify-15: 开发指南
  • DIY循迹模块多路改造指南
  • 【WRF-Chem第三期】输入数据概览
  • 随笔之TDengine基准测试示例
  • LeetCode 25:K 个一组翻转链表
  • MCU中的CAN总线是什么?
  • WebRTC核心组件技术解析:架构、作用与协同机制
  • 一文掌握最新版本Monocle3单细胞轨迹(拟时序)分析
  • 如何将JPG、PNG、GIF图像转换成PDF、SVG、EPS矢量图像
  • Rust基础[part9]_返回值和错误处理、模块化
  • [特殊字符] 征服CPU的艺术:Rust多进程编程实战指南
  • Cortex-M处理器的优势?
  • STM32CubeIDE新建项目过程记录备忘(二)
  • FFmpeg:因码流采集与封装不同步导致录制出来的MP4文件会出现黑屏、绿屏的问题
  • Zynq SoC 中断控制系统设计与实现:基于 GPIO 的中断驱动开发
  • LocalDateTime vs Instant vs ZonedDateTime:到底该用哪个?
  • .net6的webapi项目统一封装返回值
  • 剧本杀系统 App 开发:科技赋能,重塑剧本杀游戏体验
  • 光伏气象监测系统:当阳光遇见科技
  • Javascript 基础总结
  • 做题笔记:某大讯飞真题28道
  • 浅拷贝和深拷贝
  • uni-app,uni.navigateTo
  • 【LangChain4j 详解】Java生态大语言模型框架设计哲学与架构原理
  • Node.js以及异步编程
  • vue模块化导入