c++函数模板基础知识

简介: c++函数模板基础知识

导航


1.函数模板及注意事项

2.用模板写个排序函数

3.普通函数与函数模板的区别

4.普通函数与函数模板的调用

5.模板的局限性

———————————————————————————————————


1.函数模板


语法:template< typename T>

typename也可以用class

其中T为通用类型,下面看两个例子

例1:


#include <iostream>
using namespace std;
//交换两个整型函数
void swapint(int &a,int &b)
{
  int temp = a;
  a = b;
  b = temp;
}
//交换两个浮点型函数
void swapDouble(double &a,double &b)
{
  double temp = a;
  a = b;
  b = temp;
}
//要写两个函数再调用
void test01()
{
  int a = 10,b = 20;
  double c = 1.1,d = 2.2;
  swapint(a,b);
  swapDouble(c,d);
  cout<<"a = "<<a<<endl;
  cout<<"b = "<<b<<endl;
  cout<<"c = "<<c<<endl;
  cout<<"d = "<<d<<endl;
}
int main()
{
  test01();
  system("pause");
  return 0;
}



为将两个不同类型的值互换我们要写两个函数,若string类型互换呢,就又要写一个函数,这时候我们就可以用到模板


例2:


#include <iostream>
using namespace std;
//函数模板
template<typename T>
void swapT(T &a,T &b)
{
  T temp = a;
  a = b;
  b = temp;
}
void test02()
{
  int a = 10,b = 20;
  double c = 1.1,d = 2.2;
  //1.自动类型推导
  swapT(a,b);
  //2.显示指定类型
  swapT<double>(c,d);
  cout<<"a = "<<a<<endl;
  cout<<"b = "<<b<<endl;
  cout<<"c = "<<c<<endl;
  cout<<"d = "<<d<<endl;
}
int main()
{
  test02();
  system("pause");
  return 0;
}


这里我们写一个模板套用即可,模板套用有两种方法

1.自动类型推导——(swap(a,b))

2.显示指定类型——(swap< int >(a,b))


注意事项

1.自动推导类型,必须推导出一致的数据类型,才可以使用

2.模板必须确定T的数据类型,才可以使用


例1:(注意1)


#include <iostream>
using namespace std;
//函数模板
template<typename T>
void swapT(T &a,T &b)
{
  T temp = a;
  a = b;
  b = temp;
}
//注意事项
void test()
{
  int a = 10;
  int b = 20;
  char c = 'a';
  swapT(a,b);  //正确
  //swapT(a,c); //错误
}
int main()
{
  test();
  system("pause");
  return 0;
}


例2:(注意2)


#include <iostream>
using namespace std;
//函数模板
template<typename T>
void func()
{
  cout<<"func()调用"<<endl;
}
//注意事项
void test()
{
  func<void>();  //这里必须加数据类型,不然无法调用
}
int main()
{
  test();
  system("pause");
  return 0;
}


———————————————————————————————————


2.利用模板写排序函数


#include <iostream>
using namespace std;
//对不同数据类型数组进行排序
//从大到小,算法为选择排序
//类型char型,int型
template<class T>
//交换数值模板
void myswap(T &a,T &b)
{
  T temp = a;
  a = b;
  b = temp;
}
//排序算法模板
template<class T>
void mysort(T arr[],int len)
{
  for(int i=0;i<len;i++)
  {
  int max = i;
  for(int j=i+1;j<len;j++)
  {
    if(arr[j]>arr[max])
    {
    max = j;
    }
  }
  if(max != i)
  {
    //交换max与i下标
    myswap(arr[i],arr[max]);
  }
  }
}
//提供打印数组模板
template<class T>
void myprintArr(T arr[],int len)
{
  for(int i=0;i<len;i++)
  {
  cout<<arr[i]<<" ";
  }
}
void test01()
{
  //测试char数组
  char charArr[] = "badcfe";
  int len = sizeof(charArr)/sizeof(char);
  mysort(charArr,len);
  myprintArr(charArr,len);
}
void test02()
{
  //测试int数组
  int intArr[] = {7,2,5,4,3,1};
  int len = sizeof(intArr)/sizeof(int);
  mysort(intArr,len);
  myprintArr(intArr,len);
}
int main()
{
  test02();
  system("pause");
  return 0;
}


利用模板写会省力一些


———————————————————————————————————


3.普通函数与函数模板的区别


1.普通函数调用可以发生隐式类型转换

2.函数模板用自动类型推导,不可以发生隐式类型转换

3.函数模板用显示指定类型,可以发生隐式类型转换


例:


#include <iostream>
using namespace std;
//普通函数
int func(int a,int b)
{
  return a+b;
}
//调用模板
template<class T>
T fun(T a, T b)
{
  return a+b;
}
void test02()
{
  int a =10,b =20;
  char c = 'a';
  //1.调用普通函数 可以会发生隐式类型转换
  cout<<func(a,b)<<endl;  
  cout<<func(a,c)<<endl;
  //2.用函数模板自动类型推导,不发生隐式类型转换
  cout<<fun(a,b)<<endl;
  //3.函数模板用显示指定类型,可以发生隐式转换
  cout<<fun<int>(a,c)<<endl;   //这里要提供指定类型
}
int main()
{
  test02();
  system("pause");
  return 0;
}



———————————————————————————————————


4.普通函数与函数模板的调用规则


1.如果函数模板与普通函数都可以调用,优先调用普通函数

2.可以通过空模板参数列表,强制调用 函数模板

3.函数模板也可以重载

4.如果函数模板可以产生更好的匹配,有限调用函数模板


调用规则1


#include <iostream>
using namespace std;
//普通函数
void myprint(int &a,int &b)
{
  cout<<"调用普通函数"<<endl;
}
//函数模板
template<class T>
void myprint(T &a,T &b)
{
  cout<<"函数模板调用"<<endl;
}
void test()
{
  int a=10,b=20;
  myprint(a,b);
}
int main()
{
  test();
  system("pause");
  return 0;
}


结果是先调用普通函数


调用规则2


#include <iostream>
using namespace std;
//普通函数
void myprint(int &a,int &b);
//{
//  cout<<"调用普通函数"<<endl;
//}
//函数模板
template<class T>
void myprint(T &a,T &b)
{
  cout<<"函数模板调用"<<endl;
}
void test()
{
  int a=10,b=20;
  myprint<>(a,b);  //使用空模板参数列表强制调用
}
int main()
{
  test();
  system("pause");
  return 0;
}



调用规则3


若函数模板发生重载,其中调用参数不同即可


调用规则4


#include <iostream>
using namespace std;
//普通函数
void myprint(int a,int b)
{
  cout<<"调用普通函数"<<endl;
}
//函数模板  
template<class T>
void myprint(T a,T b)
{
  cout<<"函数模板调用"<<endl;
}
void test()
{
  char a = 'a',b = 'c';
  myprint(a,b);   
}
int main()
{
  test();
  system("pause");
  return 0;
}



这里会调用函数模板


———————————————————————————————————


5.模板的局限性


若只传入一些普通类型的单个数据,是可以的,若传入数组或者类,就要使用具体化的方法实现


例:


#include <iostream>
using namespace std;
#include <string>
//写一个类
class Person
{
public:
  Person(string name,int age)
  {
  this->name = name;
  this->age = age;
  }
  string name;
  int age;
};
//模板 用于单个普通的类型,数组或者自定义就不行,应该用具体方法实现
template<class T>
bool compare(T a,T b)
{
  if(a==b)
  {
  return true;
  }
  else
  {
  return false;
  }
}
//写一个person类的模板,里面传入的也要改为对应的类型
template<> bool compare(Person p1,Person p2)
{
  if(p1.name == p2.name && p1.age == p2.age)
  {
  return true;
  }
  else
  {
  return false;
  }
}
void test()
{
  int a=10,b =10;
  bool ret = compare(a,b);
  //测试普通的类型
  if(ret)
  {
  cout<<"a == b"<<endl;
  }
  else
  {
  cout<<"a != b"<<endl;
  }
  //测试Person类 
  Person p1("小明",12);
  Person p2("小明",12);
  bool ret1 = compare(p1,p2);
  if(ret1)
  {
  cout<<"p1 == p2"<<endl;
  }
  else
  {
  cout<<"p1 != p2"<<endl;
  }
}
int main()
{
  test();
  system("pause");
  return 0;
}


相关文章
|
2月前
|
存储 算法 C++
C++ STL 初探:打开标准模板库的大门
C++ STL 初探:打开标准模板库的大门
112 10
|
25天前
|
安全 编译器 C++
【C++11】可变模板参数详解
本文详细介绍了C++11引入的可变模板参数,这是一种允许模板接受任意数量和类型参数的强大工具。文章从基本概念入手,讲解了可变模板参数的语法、参数包的展开方法,以及如何结合递归调用、折叠表达式等技术实现高效编程。通过具体示例,如打印任意数量参数、类型安全的`printf`替代方案等,展示了其在实际开发中的应用。最后,文章讨论了性能优化策略和常见问题,帮助读者更好地理解和使用这一高级C++特性。
42 4
|
25天前
|
算法 编译器 C++
【C++】模板详细讲解(含反向迭代器)
C++模板是泛型编程的核心,允许编写与类型无关的代码,提高代码复用性和灵活性。模板分为函数模板和类模板,支持隐式和显式实例化,以及特化(全特化和偏特化)。C++标准库广泛使用模板,如容器、迭代器、算法和函数对象等,以支持高效、灵活的编程。反向迭代器通过对正向迭代器的封装,实现了逆序遍历的功能。
34 3
|
28天前
|
编译器 C++
【c++】模板详解(1)
本文介绍了C++中的模板概念,包括函数模板和类模板,强调了模板作为泛型编程基础的重要性。函数模板允许创建类型无关的函数,类模板则能根据不同的类型生成不同的类。文章通过具体示例详细解释了模板的定义、实例化及匹配原则,帮助读者理解模板机制,为学习STL打下基础。
31 0
|
2月前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
2月前
|
编译器 程序员 C++
【C++打怪之路Lv7】-- 模板初阶
【C++打怪之路Lv7】-- 模板初阶
18 1
|
2月前
|
存储 前端开发 C++
C++ 多线程之带返回值的线程处理函数
这篇文章介绍了在C++中使用`async`函数、`packaged_task`和`promise`三种方法来创建带返回值的线程处理函数。
79 6
|
2月前
|
C++
C++ 多线程之线程管理函数
这篇文章介绍了C++中多线程编程的几个关键函数,包括获取线程ID的`get_id()`,延时函数`sleep_for()`,线程让步函数`yield()`,以及阻塞线程直到指定时间的`sleep_until()`。
37 0
C++ 多线程之线程管理函数
|
2月前
|
编译器 C语言 C++
C++入门3——类与对象2-2(类的6个默认成员函数)
C++入门3——类与对象2-2(类的6个默认成员函数)
38 3
|
2月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
336 1