函数模板
- 格式:ppt
- 大小:229.00 KB
- 文档页数:25


C++函数模板详解
经常有碰到函数模块的应用,很多书上也只是略有小讲一下,今天又狂碰到函数模块,无奈特地
找来C++编程经典<>翻阅一遍,终于有所全面了解.....
C++函数模块基础知识:
一. 问题:
强类型语言要求我们为所有希望比较的类型都实现一个实例 int min( int a, int b ) {
return a < b ? a : b;
}
double min( double a, double b ) {
return a < b ? a : b;
}
有一种方法可替代为每个min()实例都显式定义一个函数的方法这种
方法很有吸引力但是也很危险.那就是用预处理器的宏扩展设施例
如 : #define min(a,b) ((a) < (b) ? (a) : (b))
在复杂调用的情况下,它的行为是不可预期的,这是因为它的两个参
数值都被计算两次. 一次是在a 和b 的测试中另一次是在宏的返回
值被计算期间.
#include
#define min(a,b) ((a) < (b) ? (a) : (b))
const int size = 10;
int ia[size];
int main() {
int elem_cnt = 0;
int *p = &ia[0]; // 计数数组元素的个数
while ( min(p++,&ia[size]) != &ia[size] )
++elem_cnt;
cout << "elem_cnt : " << elem_cnt
<< "\texpecting: " << size << endl;
return 0;
}
执行该程序的结果是下面不正确的计算结果: elem_cnt : 5 expecting: 10 min()的宏扩展在这种情况下会失败因为应用在指针实参p 上的后置
递增操作随每次扩展而被应用了两次
二 . 解决办法:
函数模板提供了一种机制通过它我们可以保留函数定义和函数调用
聊聊C++模板函数与⾮模板函数的重载
前⾔
函数重载在C++中是⼀个很重要的特性。之所以有了它才有了操作符重载、iostream、函数⼦、函数适配器、智能指针等⾮常有⽤的东西。
平常在实际的应⽤中多半要么是模板函数与模板函数重载,或者是⾮模板函数与⾮模板重载。⽽让模板函数与⾮模板函数重载的情况却很
少。
前段时间在项⽬中偶然遇到了⼀个模板函数与⾮模板函数重载的诡异问题,⼤概相当于下⾯这种情况:
template
int compare(const T& lhs, const T& rhs)
{
std::cout << "template compare" << std::endl;
return 0;
}
int compare(const char* lhs, const char* rhs)
{
std::cout << "ordinary compare" << std::endl;
return 0;
}
int main(int argc, char *argv[])
{
char c1[] = "hello";
char c2[] = "hello";
compare(c1, c2);
}
最终输出打印的是什么呢?嗯哼?
分析
开始的时候我以为理所当然输出的是“ordinary compare”,就没有在意这⾥。结果在程序的其他地⽅调试了很久死活找不出问题的所在,然
后索性就把那个⾮模板函数改成了模板函数的偏特化函数,之前出现的问题就消失了。这才发现问题出现在之前的模板函数与⾮模板函数重
载那⾥了。那时候的情况就跟上⾯的代码的情况差不多⼀个意思。回到上⾯代码输出的打印结果上来,在⼏个主流的编译器上的输出结果是这样的:
g++ 4.8.1 : template compare
clang 3.4.2 : template compare
vs2010 :ordinary compare
先来看看C++中模板函数与⾮模板函数的重载决议步骤:
函数考试答题模板及答案
一、函数的定义域和值域
题目: 求函数 \( f(x) = \frac{1}{x^2 - 4} \) 的定义域和值域。
答题模板:
1. 定义域: 首先确定函数的定义域,即函数中分母不为零的
\( x \) 的值。对于函数 \( f(x) = \frac{1}{x^2 - 4} \),我们需要找到使得 \( x^2 - 4 \neq 0 \) 的 \( x \) 值。解方程 \( x^2 - 4 = 0 \) 得到 \( x
= \pm 2 \),因此定义域为 \( x \in \mathbb{R} \setminus \{-2, 2\} \)。
2. 值域: 接下来确定函数的值域。由于 \( x^2 - 4 \) 总是正数或负数(除了 \( x = \pm 2 \)),函数 \( f(x) \) 的值域为所有非零实数,即 \( f(x) \in \mathbb{R} \setminus \{0\} \)。
答案:
定义域:\( x \in \mathbb{R} \setminus \{-2, 2\} \) 值域:\( f(x) \in \mathbb{R} \setminus \{0\} \)
二、函数的单调性
题目: 判断函数 \( g(x) = x^3 - 3x \) 在区间 \( (-\infty, +\infty) \)
上的单调性。
答题模板:
1. 求导数: 求函数 \( g(x) \) 的导数 \( g'(x) \)。对于 \( g(x) = x^3
- 3x \),导数为 \( g'(x) = 3x^2 - 3 \)。
2. 分析导数: 分析导数 \( g'(x) \) 的符号。令 \( g'(x) = 0 \) 得到
\( x = \pm 1 \)。在 \( x < -1 \) 和 \( x > 1 \) 时,\( g'(x) > 0 \),说明函数在这些区间内单调递增;在 \( -1 < x < 1 \) 时,\( g'(x) < 0 \),说明函数在这个区间内单调递减。
C++Template基础篇(⼀):函数模板详解
Template所代表的泛型编程是C++语⾔中的重要的组成部分,我将通过⼏篇blog对这半年以来的学习做⼀个系统的总结,本⽂
是基础篇的第⼀部分。
为什么要有泛型编程
C++是⼀门强类型语⾔,所以⽆法做到像动态语⾔(python javascript)那样⼦,编写⼀段通⽤的逻辑,可以把任意类型的变
量传进去处理。泛型编程弥补了这个缺点,通过把通⽤逻辑设计为模板,摆脱了类型的限制,提供了继承机制以外的另⼀种抽
象机制,极⼤地提升了代码的可重⽤性。
注意:模板定义本⾝不参与编译,⽽是编译器根据模板的⽤户使⽤模板时提供的类型参数⽣成代码,再进⾏编译,这⼀过程被
称为模板实例化。⽤户提供不同的类型参数,就会实例化出不同的代码。
函数模板定义
把处理不同类型的公共逻辑抽象成函数,就得到了函数模板。
函数模板可以声明为inline或者constexpr的,将它们放在template之后,返回值之前即可。
普通函数模板
下⾯定义了⼀个名叫compare的函数模板,⽀持多种类型的通⽤⽐较逻辑。
template
int compare(const T& left, const T& right) {
if (left < right) {
return -1;
}
if (right < left) {
return 1;
}
return 0;
}
compare(1, 2); //使⽤模板函数
成员函数模板
不仅普通函数可以定义为模板,类的成员函数也可以定义为模板。
class Printer {
public:
template
void print(const T& t) {
cout << t <
}
};
Printer p;
p.print("abc"); //打印abc
为什么成员函数模板不能是虚函数(virtual)?
这是因为c++ compiler在parse⼀个类的时候就要确定vtable的⼤⼩,如果允许⼀个虚函数是模板函数,那么compiler就需要在