25.C++- 泛型编程之函数模板(详解)
2018-06-27 10:06:20来源:未知 阅读 ()
本章学习:
1)初探函数模板
2)深入理解函数模板
3)多参函数模板
4)重载函数模板
当我们想写个Swap()交换函数时,通常这样写:
void Swap(int& a, int& b) { int c = a; a = b; b = c; }
但是这个函数仅仅只能支持int类型,如果我们想实现交换double,float,string等等时,就还需要从新去构造Swap()重载函数,这样不但重复劳动,容易出错,而且还带来很大的维护和调试工作量。更糟的是,还会增加可执行文件的大小.
所以C++引入了泛型编程概念
在C++里,通过函数模板和类模板来实现泛型编程(类模板在下章将讲解)
函数模板
- 一种特殊的函数,可通过不同类型进行调用
- 函数模板是C++中重要的代码复用方式
- 通过template关键字来声明使用模板
- 通过typename关键字来定义模板类型
比如:
template <typename T> //声明使用模板,并定义T是一个模板类型 void Swap(T& a, T& b) //紧接着使用T { T c = a; a = b; b = c; }
当我们使用int类型参数来调用上面的Swap()时,则T就会自动转换为int类型.
函数模板的使用
- 分为自动调用和显示调用
例如,我们写了一个Swap函数模板,然后在main()函数里写入:
int a=0; int b=1; Swap(a,b); //自动调用,编译器根据a和b的类型来推导 float c=0; float d=1; Swap<float>(c,d); //显示调用,告诉编译器,调用的参数是float类型
初探函数模板
写两个函数模板,一个用来排序数组,一个用来打印数组,代码如下:
#include <iostream> #include <string> using namespace std; template < typename T > void Sort(T a[], int len) { for(int i=1;i<len;i++) for(int j=0;j<i;j++) if(a[i]<a[j]) { T t=a[i]; a[i]=a[j]; a[j]=t; } } template < typename T > void Println(T a[], int len) { for(int i=0; i<len; i++) { cout << a[i] << ", "; } cout << endl; } int main() { int a[5] = {5, 3, 2, 4, 1}; Sort(a, 5); //自动调用,编译器根据a和5的类型来推导 Println<int>(a, 5); //显示调用,告诉编译器,调用的参数是int类型 string s[5] = {"Java", "C++", "Pascal", "Ruby", "Basic"}; Sort(s, 5); Println(s, 5);
return 0; }
运行打印:
1,2,3,4,5, Basic,C++, Java,Pascal,Ruby,
深入理解函数模板
为什么函数模板能够执行不同的类型参数?
答:
- 其实编译器对函数模板进行了两次编译
- 第一次编译时,首先去检查函数模板本身有没有语法错误
- 第二次编译时,会去找调用函数模板的代码,然后通过代码的真正参数,来生成真正的函数。
- 所以函数模板,其实只是一个模具,当我们调用它时,编译器就会给我们生成真正的函数.
试验函数模板是否生成真正的函数
通过两个不同类型的函数指针指向函数模板,然后打印指针地址是否一致,代码如下:
#include <iostream> using namespace std;
template <typename T> void Swap(T& a, T& b) { T c = a; a = b; b = c; } int main() { void (*FPii)(int&,int&); FPii = Swap ; //函数指针FPii void (*FPff)(float&,float&); FPff = Swap ; //函数指针FPff cout<<reinterpret_cast<void *>(FPii)<<endl; cout<<reinterpret_cast<void *>(FPff)<<endl; //cout<<reinterpret_cast<void *>(Swap)<<endl; //编译该行会出错,因为Swap()只是个模板,并不是一个真正函数 return 0; }
运行打印:
0x41ba98 0x41ba70
可以发现两个不同类型的函数指针,指向同一个函数模板,打印的地址却都不一样,显然编译器默默帮我们生成了两个不同的真正函数
多参数函数模板
在我们之前小节学的函数模板都是单参数的, 其实函数模板可以定义任意多个不同的类型参数,例如:
template <typename T1,typename T2,typename T3> T1 Add(T2 a,T3 b) { return static_cast<T1>(a+b); }
注意:
- 工程中一般都将返回值参数作为第一个模板类型
- 如果返回值参数作为了模板类型,则必须需要指定返回值模板类型.因为编译器无法推导出返回值类型
- 可以从左向右部分指定类型参数
接下来开始试验多参数函数模板
#include <iostream> using namespace std; template<typename T1,typename T2,typename T3> T1 Add(T2 a,T3 b) { return static_cast<T1>(a+b); } int main() { // int a = add(1,1.5); //该行编译出错,没有指定返回值类型 int a = Add<int>(1,1.5); cout<<a<<endl; //2 float b = Add<float,int,float>(1,1.5); cout<<b<<endl; //2.5 return 0; }
运行打印:
2 2.5
重载函数模板
- 函数模板可以像普通函数一样被重载
- 函数模板不接受隐式转换
- 当有函数模板,以及普通重载函数时,编译器会优先考虑普通函数
- 如果普通函数的参数无法匹配,编译器会尝试进行隐式转换,若转换成功,便调用普通函数
- 若转换失败,编译器便调用函数模板
- 可以通过空模板实参列表来限定编译器只匹配函数模板
接下来开始试验重载函数模板
#include <iostream> using namespace std; template <typename T> T Max(T a,T b) { cout<<"T Max(T a,T b)"<<endl; return a > b ? a : b; } template <typename T> T Max(T* a,T* b) //重载函数模板 { cout<<"T Max(T* a,T* b)"<<endl; return *a > *b ? *a : *b; } int Max(int a,int b) //重载普通函数 { cout<<"int Max(int a,int b)"<<endl; return a > b ? a : b; } int main() { int a=0; int b=1; cout<<"a:b="<<Max(a,b) <<endl ; //调用普通函数 Max(int,int) cout<<"a:b="<<Max<>(a,b)<<endl; //通过模板参数表 调用 函数模板 Max(int,int) cout<<"1.5:2.0="<<Max(1.5,2.0)<<endl; //由于两个参数默认都是double,所以无法隐式转换,则调用函数模板 Max(double,double) int *p1 = new int(1); int *p2 = new int(2); cout<<"*p1:*p2="<<Max(p1,p2)<<endl; // 调用重载函数模板 Max(int* ,int* ) cout<<"'a',100="<< Max('a',100)<<endl; //将char类型进行隐式转换,从而调用普通函数 Max(int,int) delete p1; delete p2; return 0; }
运行打印:
int Max(int a,int b) a:b=1
T Max(T a,T b) a:b=1
T Max(T a,T b) 1.5:2.0=2
T Max(T* a,T* b) *p1:*p2=2
int Max(int a,int b) 'a',100=100
接下来下章来学习: 26.C++- 泛型编程之类模板(详解)
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- C代做 C++代做 C++编程代做 C++程序代做 2020-04-29
- 第七章 2.泛型编程(模板) 2020-04-04
- linux环境下的时间编程 2020-03-27
- C、C++ 标准输入重定向 & 万能头 - 编程技巧 2020-03-20
- C++ 常用编程--Swap函数有几种写法? 2020-02-26
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash