C++模板学习

模板初阶

 泛型编程

函数重载的几个不好的地方:

1.代码的复用率低,新类型出现时,就需要增加对应的函数。例如交换函数的书写时,就能体现出复用率低。

2.代码的可维护性比较低,一个出错可能让所有的重载均出错。

泛型编程:编写与类型无关的通用代码,是代码复用的一种手段,模板是泛型编程的基础。

模板又分为函数模板和类模板。

函数模板 

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

typename是用来定义模板参数关键字,也可以使用class(不能使用struct代替class)

函数模板的原理

模板参数实例化分为:隐式实例化和显式实例化。

隐式实例化就是让编译器根据实参推演模板参数的实际类型,显式实例化就是在函数名后的<>中指定模板参数的实际类型。

注意隐式实例化中模板参数列表只有一个T,所以不能有多于一种的参数类型需要去推演。例如int,double两种类型.

template<class T>
T Add(const T& left,const T& right)
{
  return left+right;
}
int main()
{
  int a1=10,a2=20;
  double d1=10.0,d2=20.0;
  Add(a1,a2);
  Add(d1,d2);
  //Add(a1,d1);不能通过编译
  Add(a1,(int)d1);
  Add<int>(a1,d1);
  return 0;
}

 需要注意的点:

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

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

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

类模板

类模板的定义格式 

 

#include<iostream>
#include<cstdio>
#include<assert.h>
#include<algorithm>
using namespace std;
template<class T>
class Vector
{
public:
  Vector(size_t m_capacity=10)
  :pdata(new T[capacity])
  ,size(0)
  ,capacity(m_capacity)
  {}//构造函数初始化
  ~Vector();//使用析构函数在类中声明,在类外定义
  void PushBack(const T& data)
  {
    pdata[size++]=data;
  }
  void PopBack()
  {
    size--;
  }
  size_t Size()
  {
    return size;
  }
  T& operator[](size_t pos)
  {
    assert(pos<size);
    return pdata[pos];
  }
private:
  T* pdata;
  size_t size;
  size_t capacity;
};
//类模板中函数放在类外进行定义时,需要加模板参数列表
template<class T>
Vector<T>::~Vector()
{
  if(pdata)
  {
    delete[] pdata;
  }
}
int main()
{
  Vector<int> s1;
  s1.PushBack(1);
  s1.PushBack(2);
  Vector<double> s2;
  s2.PushBack(1.0);
  s2.PushBack(2.0);
  s2.PushBack(3.0);
  for(size_t i=0;i<s1.Size();i++)
  {
    cout<<s1[i]<<" ";
  }
  cout<<endl;
  for(size_t i=0;i<s2.Size();i++)
  {
    cout<<s2[i]<<" ";
  }
  cout<<endl;
  return 0;
}

模板进阶

非类型模板参数 

 模板参数分类 :类型形参与非类型形参。

类型形参出现在模板参数列表中,跟在class或者typename之类的参数类型名称。

非类型形参,就是用另一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。

****常量的类型只能是:整形(及相关类型),指针,引用。       浮点数类对象以及字符串不允许作为非类型模板参数。

****传入的时候必须是const类型的数据

模板的特化

模板的特化是指在原模板类的基础上,针对特殊类型所进行的特殊化的实现方式。模板特化分为函数模板特化和类模板特化。

函数模板特化步骤:

基础函数模板---->template后面接一对空的尖括号<>   ------------>函数名后跟一对尖括号,尖括号中指定需要特化的类型

------------------->           函数形参表必须要和模板函数的基础参数类型完全相同。

template<>
bool Isequal<char*>(char*& left,char*& right)
{
  if(strcmp(left,right)>0)
  {
    return true;
  }
  return false;
}

类模板特化:

分为全特化和偏特化。

全特化就是将模板参数列表中所有的参数都确定化。

偏特化有以下两种表现方式:

**部分特化   将模板参数类表中的一部分参数特化

**参数更进一步的限制        偏特化并不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本。

类模板特化应用之类型萃取

1.memcpy,strcpy均是浅拷贝。如果拷贝自定义类型对象,要确定自定义类型对象是浅拷贝还是深拷贝。深拷贝则不能使用memcpy,strcpy

2.使用循环复制的方式代码的效率比较低。 

3.为了将内置类型与自定义类型区分开,可以采用类型萃取。

模板分离编译

经历步骤:

预处理---->编译---->汇编----->链接

模板总结

优点:

  1.  模板复用了代码,节省资源,更快的迭代开发

  2. 增强了代码的灵活性

  3. 进行完封装以后使用起来更加方便,维护性高

缺点:

  1. 导致代码膨胀问题,编译时间也会变长。
  2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误。
分数阶傅里叶变换(Fractional Fourier Transform, FRFT)是对传统傅里叶变换的拓展,它通过非整数阶的变换方式,能够更有效地处理非线性信号以及涉及时频局部化的问题。在信号处理领域,FRFT尤其适用于分析非平稳信号,例如在雷达、声纳和通信系统中,对线性调频(Linear Frequency Modulation, LFM)信号的分析具有显著优势。LFM信号是一种频率随时间线性变化的信号,因其具有宽频带和良好的时频分辨率,被广泛应用于雷达和通信系统。FRFT能够更精准地捕捉LFM信号的时间和频率信息,相比普通傅里叶变换,其性能更为出色。 MATLAB是一种强大的数计算和科学计算工具,拥有丰富的函数库和用户友好的界面。在MATLAB中实现FRFT,通常需要编写自定义函数或利用信号处理工具箱中的相关函数。例如,一个名为“frft”的文件可能是用于执行分数阶傅里叶变换的MATLAB脚本或函数,并展示其在信号处理中的应用。FRFT的正确性验证通常通过对比变换前后信号的特性来完成,比如评估信号的重构质量、信噪比等。具体而言,可以通过计算原始信号与经过FRFT处理后的信号之间的相似度,或者对比LFM信号的关键参数(如初始频率、扫频率和持续时间)是否在变换后得到准确恢复。 在MATLAB代码实现中,通常包含以下步骤:首先,生成LFM信号模型,设定其初始频率、扫频率、持续时间和采样率等参数;其次,利用自定义的frft函数对LFM信号进行分数阶傅里叶变换;接着,使用MATLAB的可视化工具(如plot或imagesc)展示原始信号的时域和频域表示,以及FRFT后的结果,以便直观对比;最后,通过计算均方误差、峰信噪比等指标来评估FRFT的性能。深入理解FRFT的数学原理并结合MATLAB编程技巧,可以实现对LFM信号的有效分析和处理。这个代码示例不仅展示了理论知识在
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值