本站首页    管理页面    写新日志    退出


«July 2025»
12345
6789101112
13141516171819
20212223242526
2728293031


公告

谦卑,荣誉,牺牲,英勇,怜悯,诚实,精神,公正。


我的分类(专题)

日志更新

最新评论

留言板

链接

 

 


Blog信息
blog名称:
日志总数:183
评论数量:698
留言数量:7
访问次数:3016970
建立时间:2005年12月29日




[编程学习]C++ 函数模板学习总结
文章收藏,  软件技术

newqiang 发表于 2006/12/7 15:12:48

  刚刚看到一个类模板,还没学习,过几天再学.先把函数模板写下来.   template <class Type, int size>    Type min(Type (&array)[size]);         这个size不是函数的参数,而是模板的参数,在编译器开始编译之前就应该给出其值.这样使用这个模板是错误的: void fun( int pval[9] )            {                     int jval = min(pval);   //error!!            } 因为我们知道,函数在传递数组作为参数的时候,传递的并不是数组的拷贝,而是数组的指针值,所以此 函数中的pval传进去的时候,并没有把9这个数字传递给size这个参数.也可以说是这个pval不能被当作左值来使用.   template <typename Type, int size>    Type min(Type (&array)[size]);是一样的,只是typename是c++标准之后出现的.  当Type是一个类时,如果我们在模板中使用Type::name时,编译器永远不会把它当作一个类型来处理,如果这是一个类型,你要在模板中这样写:typename Type::name *p;这样编译器将认为这是定义了一个类型而不是一个乘法.   根据一组获更多实际类型或者值来通过模板构造函数的过程称为模板实例化.  用函数实参的类型来决定模板实参的类型和值的过程被称为模板实参推演.   强制指定实参类型:        typedef  int  (&rai)[10];               typedef  int  (&rad)[20];  void func( int  (*)  (rai) );   //定义了一个参数为函数指针的函数fun  void func( int  (*)  (rad) );   //重载了函数fun  如果使用func( &min);的话,实参推演就会失败.可以使用强制指定来消除编译错误:  func( static_cast<double (*) (rad)>  (&min));尖括号中的double (*) (rad)是强制指定模板参数而用.   上面的例子中也可以使用显式模板实参来消除编译错误,而且更好.  template <class T1,class T2,class T3>              T1 sum(T2,T3);        这个模板定义是合法的,也有用,但是编译器在实例化的时候无法推演出T1的类型,因此会报错,此时只有使用显式模板实参来消除错误,使用的时候应该这么使用:  int  data = sum<int,int,int>(1,2);和使用"参数有默认值的函数"一样,显式模板实参书写时如果后面的参数编译器可以推演出来,则不需要写,上面的例子可写成:int  data = sum<int>(1,2);   模板的编译模式包括包含编译模式以及分离编译式.分离编译模式在定义时前面应该加上export.然后使用改模板时只需要声明一下即可.无论一个模板被实例化多少次,都不会影响最终结果,但是这会浪费编译的时间.   模板的显式特化:  不知道隐式特化是啥东西.但是显式特化的意思是:当一类东西中出了一渣滓的时候,为了对外接口的统一,或者说是为了家丑不可外扬,有必要把它单独拿出来写一下,然后使他可以和这个类中的所有东西步伐一致.例如:  template <class T>              T max ( T ,T);//这是一个返回其中较大的那个值的函数模板.  但是为了比较字符串,我们不得不对它进行一个特化:  typedef  const char*  PCC;        template<> PCC  max<PCC>(PCC,PCC);//max后面跟的<>中的PCC是模板的实参,如果这个实参可以被编译器推演出来,那么就可以省略,所以这个可以写成:template<> PCC  max(PCC,PCC);         重载函数模板.不过是把模板定义时那个下面的函数名不变,参数变而已,而且每重载一次,上面的template都要重写一次.与模板的显式特化好象是不同方向上的扩展.重载之后,编译器在实例化时采用参数最匹配就用谁的原则来选择模板和同名的函数.   依赖于函数模板的名字解析发生在模板实例化时.不依赖函数模板的名字解析发生在解析模板时.   下面这段代码的问题很难被发现:  #define min(a,b)  ( (a) < (b) ? (a) : (b) )  while(p<100) a=min(p++,50);        因为p被展开之后加了两次,违背了作者的愿意,所以尽量不要使用define. Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=786231


阅读全文(15344) | 回复(1) | 编辑 | 精华
 


回复:C++ 函数模板学习总结
文章收藏,  软件技术

阿萨(游客)发表评论于2009/5/15 14:33:00

void func( int  (*)  (rai) );   //定义了一个参数为函数指针的函数fun  void func( int  (*)  (rad) );   //重载了函数fun 这个是重载吗,数量参数名不同外没什么啊?  


个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除
 


» 1 »

发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.047 second(s), page refreshed 144759166 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号