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"iostream"
using namespace std;

#define min(a,b)  (a)<(b)?(a):(b)

const int size = 10;
int num[size];

void main()
{
    int elem_cnt = 0;
    int *p = &num[0];
    // 计数数组元素的个数
    while (min(p++,(&num[size])) != (&num[size]))
        ++elem_cnt;
    cout << "elem_cnt : " << elem_cnt<< "\texpecting: " << size << endl;

    system("pause");
}

 

执行该程序的结果是下面不正确的计算结果:  elem_cnt : 5 expecting: 10

min()的宏扩展在这种情况下会失败因为应用在指针实参p 上的后置递增操作随每次扩展而被应用了两次

 

 . 解决办法:

 

函数模板提供了一种机制,通过它我们可以保留函数定义和函数调用的语义,在一个程序位置上封装了一段代码,确保在函数调用之前实参只被计算一次.

 

函数模板提供一个种用来自动生成各种类型函数实例的算法,程序员对于函数接口参数和返回类型中的全部或者部分类型进行参数化(parameterize),而函数体保持不变.(这也是函数模板与函数重载的不同之处)

 

下面是min()的函数模板定义

 

template<typename T>

 

T min( T a, T b ) {

 

return a < b ? a : b;

 

}

 

.  具体操作

 

关键字template 总是放在模板的定义与声明的最前面,关键字后面是用逗号分隔的模板参数表(template parameter list),它用尖括号<> 一个小于号和一个大于号括起来,该列表是模板参数表不能为空模板参数,可以是一个模板类型参数(template typeparameter)它代表了一种类型,也可以是一个模板非类型参数(template nontype parameter)它代表了一个常量表达式。模板类型参数由关键字class 或typename 后加一个标识符构成在函数的模板参数表中,这两个关键字的意义相同。

模板非类型参数由一个普通的参数声明构成模板非类型参数,表示该参数名代表了一个潜在的值,而该值代表了模板定义中的一个常量,例如size 是一个模板非类型参数它代表arr 指向的数组的长度。

template<typename T>

T min( T (&arr) [size] );

当函数模板min()被实例化时,size 的值会被一个编译时刻已知的常量值代替.

函数定义或声明跟在模板参数表后,除了模板参数是类型指示符或常量值外,函数模板的定义看起来与非模板函数的定义相同。template<typename T>

T min( const T (&r_array)[size] )//个人觉得这是一个数组指针
{
/* 找到数组中元素最小值的参数化函数 */
T min_val = r_array[0];
for ( int i = 1; i < size; ++i )
{
  if ( r_array[i] < min_val )
  min_val = r_array[i];
}
return min_val;
}

 

实例:

#include"iostream"
using namespace std;

const int size = 5;
int num[size] = { 5, 2, 4, 3, 6 };

template<typename T>
T min(const T(&n_array)[size])//此处应该是传递一个数组指针
{
    T min_val = n_array[0];
    for (int i = 0; i < size; ++i)
    {
        if (n_array[i] < min_val)
            min_val = n_array[i];
    }
    return min_val;
}

void main()
{
    cout<<min(num)<<endl;
    system("pause");
}

输出:2

四.几点注意

  如果在全局域中声明了与模板参数同名的对象函数或类型,则该全局名将被隐藏。

在下面的例子中tmp 的类型不是double 是模板参数Type。

typedef double T;//全局域中声明了与模板参数同名的类型

template<typename T>

T min( T a, T b )

{

// tmp 类型为模板参数 T

// 不是全局 typedef

T tmp = a < b ? a : b;

return tmp;

}

 

②  在函数模板定义声明的对象或类型不能与模板参数同名

 

template<typename T>

 

T min( T a, T b )

 

{

 

// 错误重新声明模板参数 T

 

typedef double T;

 

T tmp = a < b ? a : b;

 

return tmp;

 

}

 

  模板类型参数名可以被用来指定函数模板的返回值

 

// ok: T1 表示 min() 的返回类型

 

// T2 和 T3 表示参数类型

 

template<typename T1,T2,T3>

 

T1 min( T2, T3 );

 

 

 

 

 

 

posted @ 2016-11-07 11:14  ren_zhg1992  阅读(113)  评论(0)    收藏  举报