参考:http://blog.csdn.net/beyondhaven/article/details/4204345

参考:http://blog.csdn.net/joeblackzqq/article/details/7460704

1.函数模板的声明和模板函数的生成

1.1函数模板的声明

函数模板可以用来创建一个通用的函数,以支持多种不同的形参,避免重载函数的函数体重复设计。它的最大特点是把函数使用的数据类型作为参数。

函数模板的声明形式为:

template<typename 数据类型参数标识符>

<返回类型><函数名>(参数表)

{

    函数体

}

其中,template是定义模板函数的关键字;template后面的尖括号不能省略;typename(或class)是声明数据类型参数标识符的关键字,用以说明它后面的标识符是数据类型标识符。这样,在以后定义的这个函数中,凡希望根据实参数据类型来确定数据类型的变量,都可以用数据类型参数标识符来说明,从而使这个变量可以适应不同的数据类型。例如:

template<typename T>

T fuc(T x, int y)

{

T x;

//……

}

如果主调函数中有以下语句:

double d;

int a;

fuc(d,a);

则系统将用实参d的数据类型double去代替函数模板中的T生成函数:

double fuc(double x,int y)

{

double x;

//……

}

函数模板只是声明了一个函数的描述即模板,不是一个可以直接执行的函数,只有根据实际情况用实参的数据类型代替类型参数标识符之后,才能产生真正的函数。

关键字typename也可以使用关键字class,这时数据类型参数标识符就可以使用所有的C++数据类型。

1.2.模板函数的生成

函数模板的数据类型参数标识符实际上是一个类型形参,在使用函数模板时,要将这个形参实例化为确定的数据类型。将类型形参实例化的参数称为模板实参,用模板实参实例化的函数称为模板函数。模板函数的生成就是将函数模板的类型形参实例化的过程。例如:

使用中应注意的几个问题:

⑴ 函数模板允许使用多个类型参数,但在template定义部分的每个形参前必须有关键字typename或class,即:

template<class 数据类型参数标识符1,…,class 数据类型参数标识符n>

<返回类型><函数名>(参数表)

{

     函数体

}

⑵ 在template语句与函数模板定义语句<返回类型>之间不允许有别的语句。如下面的声明是错误的:

template<class T>

int I;

T min(T x,T y)

{

函数体

}

⑶ 模板函数类似于重载函数,但两者有很大区别:函数重载时,每个函数体内可以执行不同的动作,但同一个函数模板实例化后的模板函数都必须执行相同的动作。

2 函数模板的异常处理

函数模板中的模板形参可实例化为各种类型,但当实例化模板形参的各模板实参之间不完全一致时,就可能发生错误,如:

template<typename T>

void min(T &x, T &y)

{  return (x<y)?x:y;  }

void func(int i, char j)

{

min(i, i);

min(j, j);

min(i, j);

min(j, i);

}

例子中的后两个调用是错误的,出现错误的原因是,在调用时,编译器按最先遇到的实参的类型隐含地生成一个模板函数,并用它对所有模板函数进行一致性检查,例如对语句

min(i, j);

先遇到的实参i是整型的,编译器就将模板形参解释为整型,此后出现的模板实参j不能解释为整型而产生错误,此时没有隐含的类型转换功能。解决此种异常的方法有两种:

⑴采用强制类型转换,如将语句min(i, j);改写为min(i,int( j));

⑵用非模板函数重载函数模板

方法有两种:

① 借用函数模板的函数体

此时只声明非模板函数的原型,它的函数体借用函数模板的函数体。如改写上面的例子如下:

template<typename T>

void min(T &x, T &y)

{  return (x<y)?x:y;  }

int min(int,int);

void func(int i, char j)

{

min(i, i);

min(j, j);

min(i, j);

min(j, i);

}

执行该程序就不会出错了,因为重载函数支持数据间的隐式类型转换。

② 重新定义函数体

就像一般的重载函数一样,重新定义一个完整的非模板函数,它所带的参数可以随意。C++中,函数模板与同名的非模板函数重载时,应遵循下列调用原则:

• 寻找一个参数完全匹配的函数,若找到就调用它。若参数完全匹配的函数多于一个,则这个调用是一个错误的调用。

• 寻找一个函数模板,若找到就将其实例化生成一个匹配的模板函数并调用它。

• 若上面两条都失败,则使用函数重载的方法,通过类型转换产生参数匹配,若找到就调用它。

•若上面三条都失败,还没有找都匹配的函数,则这个调用是一个错误的调用。

c++类模板及参数类型的运行时判断

  1. /*
  2. C++类模板及参数类型的运行时判断(typeid)
  3. */
  4. #include <stdio.h>
  5. #include <typeinfo>
  6. #include <vector>
  7. using namespace std;
  8. template<class T>
  9. class Exercise
  10. {
  11. public:
  12. typedef T Type;
  13. typedef vector < Type > VT;
  14. Exercise(int n);
  15. void Display();
  16. private:
  17. VT dv;
  18. };
  19. template<class T>
  20. Exercise<T>::Exercise(int n)
  21. {
  22. T v;
  23. printf("type: %s\n", typeid(T).name());
  24. for(int i = 0; i < n; i++)
  25. {
  26. v = 1.1 * (i+1);
  27. dv.push_back(v);
  28. }
  29. }
  30. template<class T>
  31. void Exercise<T>::Display()
  32. {
  33. char fmt[2][10] = {"%d\t", "%.2f\t"};
  34. char *p = fmt[0];
  35. if(typeid(T) == typeid(double) || typeid(T) == typeid(float))
  36. p = fmt[1];
  37. for(typename vector<T>::iterator it = dv.begin(); it != dv.end(); it++)
  38. {
  39. printf(p, *it);
  40. }
  41. printf("\n\n");
  42. }
  43. int main()
  44. {
  45. Exercise<double> ex1(5);
  46. ex1.Display();
  47. Exercise<float> ex2(5);
  48. ex2.Display();
  49. Exercise<int> ex3(5);
  50. ex3.Display();
  51. Exercise<long> ex4(5);
  52. ex4.Display();
  53. printf("\n");
  54. printf("%s\n", typeid(ex1).name());
  55. printf("%s\n", typeid(ex2).name());
  56. printf("%s\n", typeid(ex3).name());
  57. printf("%s\n", typeid(ex4).name());
  58. return 0;
  59. }

[c++][语言语法]函数模板和模板函数 及参数类型的运行时判断的更多相关文章

  1. XPAND模板语言语法1.0

    XPAND模板语言语法1.0 Xpand模板语言一般写在以.xpt为结尾的文本文件中 ,以"« »" 作为开头和结尾  .Xpand语言主要包括以下几个标签: «IMPORT», ...

  2. C++函数模板&类模板

    函数模板 模板概念及语法 主要目的,简化代码,减少重复代码.基本语法格式:  template<class T> 或者 template<typename T> //末尾不加分 ...

  3. C++中的动态类型与动态绑定、虚函数、运行时多态的实现

    动态类型与静态类型 静态类型 是指不需要考虑表达式的执行期语义,仅分析程序文本而决定的表达式类型.静态类型仅依赖于包含表达式的程序文本的形式,而在程序运行时不会改变.通俗的讲,就是上下文无关,在编译时 ...

  4. python函数参数类型及其顺序

    根据inspect模块官文文档中关于函数参数类型的相关说明,python函数参数共有五种类型,按顺序分别为:POSITIONAL_ONLY.POSITIONAL_OR_KEYWORD.VAR_POSI ...

  5. T4学习- 3、创建运行时模板

    使用 Visual Studio 预处理过的文本模板,可以在运行时在应用程序中生成文本字符串. 执行应用程序的计算机不必具有 Visual Studio. 预处理过的模板有时称为"运行时文本 ...

  6. C# 语言规范_版本5.0 (第4章 类型)

    1. 类型 C# 语言的类型划分为两大类:值类型 (Value type) 和引用类型 (reference type).值类型和引用类型都可以为泛型类型 (generic type),泛型类型采用一 ...

  7. ThinkPHP第五天(提交类型判定常量IS_POST等,错误页面种类,Model实例化方式,模板中使用函数,foreach循环,模板中.语法配置)

    1.IS_GET.IS_POST.IS_PUT.IS_DELETE.IS_AJAX常量,方便快捷实现各个判断. 在Action类中还可以使用$this->isPost()等进行判断. 2.错误页 ...

  8. C++ 函数模板一(函数模板定义)

    //函数模板定义--数据类型做参数 #include<iostream> using namespace std; /* 函数模板声明 1.函数模板定义由模板说明和函数定义组成,并且一个模 ...

  9. [转]C++函数模板与模板函数

      1.函数模板的声明和模板函数的生成   1.1函数模板的声明 函数模板可以用来创建一个通用的函数,以支持多种不同的形参,避免重载函数的函数体重复设计.它的最大特点是把函数使用的数据类型作为参数. ...

随机推荐

  1. 使用Adreno Profiler分析android游戏

    有时候我们需要对自己的游戏或者别人的游戏进行分析,比如我们需要了解一个引擎的大体渲染的流程,这个时候我们可以借助一些工具,在PC上我们可以使用Microsoft PIX.Intel GPA.Nvidi ...

  2. [Linux Tips] 1. 查看端口

    查看监听的端口 # netstat -lnp

  3. log4j2.x 配置文件默认寻找顺序

    Automatic Configuration Log4j has the ability to automatically configure itself during initializatio ...

  4. String的replaceAll方法中的正则表达式用法

    项目里面 需要对已手机号码进行 如下的显示 比如15088688388 要显示为150****8388的效果 实现这个简单的效果 方法有很多 我想试试用正则表达式去实现 查了点资料最终试出来以下方法可 ...

  5. Orchard学习系列-----如何运行的

    感慨:当接触到微软这套程序时,代码实在是太好了,好的几乎都读不懂.很久之前就对这个套开源程序特别感兴趣,但读不明白也让人郁闷. 背景(Orchard官网): 可组装系统的CMS系统,OrChard在运 ...

  6. centos 6.4下安装postgresql 9.2

    我的linux版本是centos 6.4 ,准备安装postgresql 9.2 根据官方说明: http://www.postgresql.org/download/linux/redhat/ 缺省 ...

  7. 安装windowbuilder错误一例

    eclipse是3.7版本,安装了windowbuilder,大致步骤如下: http://www.cnblogs.com/gladto/archive/2011/07/21/2112836.html ...

  8. Leetcode: Count Numbers with Unique Digits

    Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n. Examp ...

  9. C# 动态链接库的创建

    首先在C#工程下面安装第三方插件包 安装方法:Tools --> Library Package Manager --> Package Manager Console Install-P ...

  10. CSS_03_04_CSS伪元素选择器

    第01步:编写css代码:wei.css @charset "utf-8"; /* 伪元素选择器 :状态 效果顺序:L V H A */ a:link.lin_01{/*超链接,未 ...