C++ template ——function template

原文:http://blog.csdn.net/qaz19870418/archive/2009/06/14/4269189.aspx

从今天开始来学习一下《C++ template》,学习c++ template的动机来自于自己在实现数据结构中的类的时候所遇到的困难。虽然以前在谭浩强老师所编写的《C++程序设计》一书中学过一点c++模板的的知识,但是那本书中讲的关于模板的知识是在是太少了,等到用的时候才发现好多东西不知道怎么用模板的只是知识来解决。

好了,废话不说了,开始进入正题。

今天学习了关于函数模板的一些知识,现在来总结一下。

1.为什么要引入模板机制?

我们知道,代码重用(code reuse)是软件工程的重要目的之一,代码重用是减少代码键入数量,缩短软件开发时间的一项非常有效地手段,而模板机制的引入正是为了能够更好的实现代码重用。

在c语言中,我们可以通过宏(macro)来实现代码的重用。例如有以下三个函数:

int max(int a, int b)

{

  return a>b?a:b;

}

float max(float a, float b)

{

  return a>b?a:b;

}

float max(float a, float b)

{

  return a>b?a:b;

}

double max(double a, double b)

{

  return a>b?a:b;

}

 这三个函数的功能是一样的,都是求a,b中较大的数,通过观察我们可以发现这三个函数除了数据的类型不一样外,其他的部分一模一样。然而我们却用了三个函数来实现这一功能,这显然不符合代码重用的原则,为此,我们可以将以上三个函数用宏实现,如下:

#define MAX(a, b) ( (a)>(b)?(a):(b))

MAX(2, 3); //计算结果为3

MAX(1.2, 3.5); //计算结果为3.5

MAX(1, 2.4); //结果为2.4

MAX(2.4, 1);   //结果为2.4

这样一来就大大简化了代码,但是这样却引入了一个问题。因为宏是类型不安全的,在编译器在预处理的时候只是进行简单的替换,而不会进行类型检查,降低了程序的安全性。

为了保留宏的简洁性以及消除其不安全性,c++中引入了模板,它既有宏的简洁方便的特点,又具有安全性。能够很好的支持代码重用。上面这个例子用模版实现如下:

template <typename T>

inline T const & max(T const& a, T const& b)

{

  return a>b?a:b;

}

max(2, 3); //计算结果为3

max (1.2, 3.5); //计算结果为3.5

max (1, 2.4); // ERROR: first T is int, second T is double

max(2.4, 1);  // ERROR: first T is double, second T is int

我们看到当我们使用max(1, 2.4)时,编译器会提示错误,原因是我们只申明了一个模版参数T, 但是在这个调用中第一个T为int, 第二个T为double,编译器不知道到底该选用哪一个来替代T,所以提示错误。

从这里我们知道了模板与宏的一个不同之处,那就是模板不支持默认的数据类型转换,而宏支持默认的数据类型转换。这样模板就能够让程序按照我们的意愿来执行,以免发生不可预料的结果。

那么,如果我们需要用函数模版max来比较1和2.4,我们该如何做呢?

我们有三种方法来解决这个问题:

方法一,将二者的类型转换成一致:

max(static_cast<double>(1), 2.4);    // OK,结果为2.4

max(2.4, static_cast<double>(1));   //// OK,结果为2.4

方法二,显式地指定类型T:

max<double>(1, 2.4);        //OK,结果为2.4

max<double>(2.4, 1);     //OK,结果为2.4

方法三,使用两个模版参数:

template <typename T1, typename T2>

inline T2  max (T1 const& a, T2 const& b)

{

    return a < b ? b : a;

}

max(1, 2.4);         //OK,结果为2.4

max(2.4, 1);       //ERROR,返回类型不匹配

我们看到,这里max(2.4, 1)编译出现错误,错误的原因是由于返回类型不匹配。那么我们该如何解决这个问题呢?

我们可以这样考虑,我们可以增加一个模版参数,用来指定模版函数的返回值,具体形式如下:

template <typename T1, typename T2, typename RT>

inline RT  max (T1 const& a, T2 const& b)

{

    return a < b ? b : a;

}

max<int, double, double>(1, 2.4);   //OK,返回2.4

max<double, int, double>(2.4, 1);   //OK,返回2.4

这样虽然问题解决了,但是通过max<int, double, double>(1, 2.4);这种方式来调用显得非常复杂,我们对以上函数稍微改动一下,就可以简化调用的形式:

template <typename RT, typename T1, typename T2>

inline RT  max (T1 const& a, T2 const& b)

{

return a < b ? b : a;

}

max<double>(1, 2.4);                             //OK,返回2.4

max<double, int, double>(1, 2.4);          //OK,与max<double>(1, 2.4); 等价

max< double>(2.4, 1);                            //OK,返回2.4

max<double, double, int>(2.4, 1);          //OK,与max< double>(2.4, 1);等价

很显然通过max<double>(1, 2.4);和max< double>(2.4, 1);来调用要简单的多。这样既解决了代码重用,又简化了调用接口,方便编程。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/qaz19870418/archive/2009/06/14/4269189.aspx

发布了90 篇原创文章 · 获赞 3 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/sunnyboychina/article/details/4346425