C++之模板与泛型编程(上):函数模板
来源:互联网 发布:linux破解wifi工具包 编辑:程序博客网 时间:2024/04/23 14:14
面向对象编程(OOP)和泛型编程都能处理在编写程序时不知道类型的情况。不同之处在于:OOP能处理类型在程序运行之前都未知的情况,而在泛型编程中,在编译时就能获知类型了。模板是C++中泛型编程的基础,一个模板就是一个创建类或者函数的蓝图或者说公式。
1. 定义模板
比如说要写一个比较两数字大小的函数,由于数字类型可能不同,int 或者float等等,这是除了我们使用重载之外,使用模板会带来更大的便利。看下面:
// code 1template <typename T>int compare(const T& v1,const T& v2){ if(v1 < v2) return -1; if(v1 > v2) return 1; return 0;}
当我们调用一个模板参数时,编译器(通常)用函数实参来为我们推断模板实参。即:当我们调用compare时,编译器使用实参的类型来确定绑定到模板参数T的类型。例如:
// code 2cout<<compare(1,19)<<endl; //T 为int
接下来,就要说说模板类型参数了。
看下面两段小程序:
// code 3template <typename T> T foo (T* p){ T tmp = *p;//tmp的类型将是指针p指向的类型 //...... return tmp;}
这里提一下,typename和class没什么不同。不过typename更加直观一些~~
再看下面一段代码:
// code 4template <unsigned N,unsigned M>int compare(const char(&p1)[N],const char (&p2)[M]){ return strcmp(p1,p2);}
上面的代码通过一个特定的类型名而非关键字class或typename来指定非类型参数。也就是在模板中定义非类型参数(nontype parameter),一个非类型参数表示一个值而非一个类型。当一个模板被实例化时,非类型参数被一个用户提供的或者编译器推断出来的值所代替。这些值必须是常量表达式,从而允许表一起在编译时实例化模板。
提示:
C++允许将变量定义成数组的引用,给予同样的道理,形参也可以是数组的引用。此时,引用形参绑定到对应的实参上,也就是绑定到数组上:
// code 5void print(int (&arr)[10]){ for(auto elem:arr){ cout << elem << endl; }}
&arr两端的括号必不可少:
// code 6f(int &arr[10]) //错误:将arr声明成了引用的数组f(int (&arr)[10]) //正确:arr是具有10个整数的整型数组的引用
所以,使用非类型模板,可以让这个函数传递任意大小的数组。
2. 编写类型无关的代码
上面的code 1,其实对我们的类型要求还是很高的,也就是说这些类型必须支持<,同时也需要支持>。实际上,如果我们真的关心类型无关和可移植性,可能需要使用less来重新定义我们的函数:
//code 7template <typename T>int compare(const T& v1,const T& v2){ if(less<T>(v1 , v2)) return -1; if(less<T>(v2 , v1) return 1; return 0;}
所以可以看出,模板程序应尽量减少对实参类型的要求。
再进一步,很多C++程序员更喜欢使用 != 而不喜欢<,原因也大概如此吧~~
3.模板编译
当编译器遇到一个模板定义时,他并不生成代码。只有当我们实力化出模板的一个特定版本时,编译器才会生成代码。当我们使用(而不是定义)模板时,编译器才会生成代码。这一特性影响了我们如何组织代码以及错误何时被检测到。
通常,当我们调用一个函数时,编译器只需要掌握函数的声明,类似的,当我们使用一个类类型的对象时,类定义必须是可用的,但成员函数的定义不必已经出现。因此,我们将类定义和函数声明放在头文件中,而普通函数和类的成员函数的定义放在源文件中。
模板则不同:为了生成一个实例化版本,编译器需要掌握函数模板或类模板成员函数的定义。因此,与非类型模板不同,模板的头文件通常既包括声明也包括定义。
通常,编译器会在三个阶段报告错误:
- 第一阶段实在编译模板本身时。在这个阶段,编译器通常不会发现很多错误。编译器可以检查语法错误。
- 第二个阶段是编译器遇到模板使用时。在此阶段,编译器仍然没有很多可检查的。对于模板的使用,编译通常会检查是参数目是否正确,还能检查参数类型是否匹配。对于类模板,编译器可以检查用户是否提供了正确数目的模板实参。
第三个阶段是模板实例化时,只有这个阶段才能发现类型相关的错误。依赖于编译器如何管理实例化,这类错误可能在链接阶段时才报告。
WARNING:
保证传递给模板的实参支持模板所要求的操作,以及这些操作在模板中能正确工作,是调用者的责任。~~
好了,函数模板就说这么多了,下一篇是 类模板~~
- C++之模板与泛型编程(上):函数模板
- C++之模板与泛型编程(上)
- C++primer 阅读笔记-模板与泛型编程(函数模板)
- C++之模板与泛型编程(一)——函数模板
- C++模板与泛型编程(1.函数模板与类模板)
- 从汇编的眼光看C++(之递归函数与模板类) ,(之泛型编程) .
- 泛型编程之“函数模板和类模板”
- C++泛型编程与函数模板
- 泛型编程与函数模板
- C++:模板与泛型编程
- [C++]模板与泛型编程
- 【C++】模板与泛型编程
- 泛型编程之函数模板
- 模板与泛型编程之定义模板
- 模板与泛型编程之模板实参推断
- C++语法基础--模板与泛型编程--函数模板,类模板,模板形参,非模板形参
- C++primer阅读笔记-模板与泛型编程(重载与模板)
- 【C/C++学院】(11)泛型编程/函数模板/类模板
- 神经网络初识
- C# 连接 SQL Server 或 Access
- Android开发笔记(九十一)工厂模式
- 安桌百度地图
- Jquery根据id获取属性的一个奇怪问题
- C++之模板与泛型编程(上):函数模板
- android Launcher 替换
- 一些可运行的C语言数据结构代码
- Windows-MFC框架程序剖析
- 从电子请柬切入,顺利融资3000万美金,“低频”的婚庆市场应该怎么做?
- iOS之一个超赞的视频直播、第三方库,直播看这个就够了,支持RTMP推流,美颜直播
- SurfaceView与Timer实现动态绘图
- 自定义UIButton图片和文字的frame
- 字符串中的空格替换