CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
花落谁家,你作主! 盛大widget设计大赛英雄榜
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  C语言

模板函数地址

楼主CodePage(代码页)2002-10-09 02:12:25 在 C/C++ / C语言 提问

template   <class   T>  
  T   add   (const   T   &a,   const   T   &b)  
  {  
      return   (a+b);  
  }  
   
  int   addint   (const   int   &a,   const   int   &b)  
  {  
      return   (a+b);  
  }  
   
  main()  
  {  
      char   ca,   cb,   cc;  
      int   ia,   ib,   ic;  
      double   da,   db,   dc;  
      void   *   ptr;  
   
      ca=cb=cc=   0;  
      ia=ib=ic=   0;  
      da=db=dc=   0;  
   
      cc   =   add(ca,   cb);  
      ic   =   add(ia,   ib);  
      dc   =   add(da,   db);  
   
      ic   =   addint(ia,   ib);  
   
      ptr   =   addint;   //得到addint()的地址,正确!  
      ptr   =   add(ia,   ib);       //错误   1  
      ptr   =   add<int>;             //错误   2  
      ptr   =   add(int,   int);   //错误   3  
  }  
   
  如何得到add<int>...的地址???? 问题点数:20、回复次数:14Top

1 楼do_do(do_do)回复于 2002-10-09 03:43:18 得分 10

ptr   =   add(ia,   ib);       //错误   1  
   
  这没有语法错但语义错。add(ia,   ib)是函数调用,其结果是返回int。用int赋值给void*自然是错误。  
   
  ptr   =   add<int>;             //错误   2  
   
  这语法错。  
   
  ptr   =   add(int,   int);   //错误   3  
   
  这也是语法错。  
   
  你要的可能是:  
  typedef   int   (*ptr)(int,   int)  
  ...  
  ptr   =   add;   //编译器应该会instantiate一个int   add(int,   int)函数然后把它的地址赋值给ptr。如果不行,试先调用add(ia,   ib)去强迫编译器instantiate   int   add(int,   int)。然后做ptr=add的赋值。  
  Top

2 楼CodePage(代码页)回复于 2002-10-09 04:32:56 得分 0

还是不行...  
   
  Top

3 楼CodePage(代码页)回复于 2002-10-09 04:35:10 得分 0

但是add<int>,add<double>的地址确实是存在的呀Top

4 楼tianxinet(越来越胖的猴子)回复于 2002-10-09 11:45:59 得分 0

应该这样获得模板函数地址:  
   
  #include   <iostream>  
   
  using   namespace   std;  
   
  template   <class   T>  
  T   add   (const   T   &a,   const   T   &b)  
  {  
      return   (a+b);  
  }  
   
  int   addint   (const   int   &a,   const   int   &b)  
  {  
      return   (a+b);  
  }  
   
   
  template   <class   T>  
  void*   fp(T   (*pf)(const   T   &a,   const   T   &b))     //该模板函数用来获得函数add的地址  
  {  
  return   pf;  
  }  
   
  void   main()  
  {  
      char   ca,   cb,   cc;  
      int   ia,   ib,   ic;  
      double   da,   db,   dc;  
      void   *   ptr;  
   
      ca=cb=cc=   0;  
      ia=ib=ic=   0;  
      da=db=dc=   0;  
   
      cc   =   add(ca,   cb);  
      ptr   =   fp<char>(&add);  
      cout<<"char   functional   pointer   is:"<<ptr<<endl;  
   
      ic   =   add(ia,   ib);  
      ptr   =   fp<int>(&add);  
      cout<<"int   functional   pointer   is:"<<ptr<<endl;  
   
      dc   =   add(da,   db);  
      ptr   =   fp<double>(&add);  
      cout<<"double   functional   pointer   is:"<<ptr<<endl;  
   
      ic   =   addint(ia,   ib);  
      ptr   =   addint;   //得到addint()的地址,正确!  
      cout<<"addint   functional   pointer   is:"<<ptr<<endl;  
     
     
  }Top

5 楼paul319(清风客)回复于 2002-10-09 12:30:01 得分 0

c++的底层实现是:模板函数并不在定义模板时具现(可以理解为得到存);而是在用到的时候(实力化并调用)才得以具现;所以向上面那样去取模板函数的地址是错误的,因为函数根本没有占用内存!Top

6 楼tianxinet(越来越胖的猴子)回复于 2002-10-09 12:38:10 得分 10

这里需要澄清两个概念:实例化&特化  
   
  特化是模板中的特有概念,所谓特化,也就是明确指定模板中的参数类型.而模板函数在特化时就可以得到地址.这一点你可以在上面我给出的代码中验证:  
  注释掉下面几行,仍然会得到相应的函数地址:  
  //cc   =   add(ca,   cb);  
  //ic   =   add(ia,   ib);  
  //dc   =   add(da,   db);  
  Top

7 楼anrxhzh(百宝箱)回复于 2002-10-09 15:47:55 得分 0

#include   <iostream>  
  #include   <string>  
   
  template   <class   T>  
  T   add   (const   T   &a,   const   T   &b)  
  {   return   (a+b);   }  
   
  int   main()  
  {  
  int   (*p)(const   int&,const   int&);  
  std::string   (*p2)(const   std::string&,const   std::string&);  
   
  p   =   add<int>;  
  p2   =   add<std::string>;  
   
  std::cout   <<   p(1,2)   <<   '   '   <<   p2("hello","   world")   <<   std::endl;  
  }  
   
  //output:  
  //3   hello   worldTop

8 楼kwok_1980(Mars)回复于 2002-10-09 16:07:46 得分 0

"但是add<int>,add<double>的地址确实是存在的呀"  
   
  >>这是什么???是class吗?  
  >>这样写是写在template   class里面的template   function吧!!?!?  
  >>没有这样的写法!至少我没有看过!  
  Top

9 楼do_do(do_do)回复于 2002-10-09 23:53:52 得分 0

昨天没上班没能直接试。今天试了一下,结果是下面的例子在Solaris,HP,IBM(AIX)上都得出正确的结果:  
   
  template   <class   T>  
  T   add(T   t1,   T   t2)  
  {  
          return   t1+t2;  
  }  
   
  typedef   int   (*Foo)(int,   int);  
   
  int   main()  
  {  
          Foo         foo   =   add;  
          cerr   <<   foo(1,   2)   <<   endl;  
  }  
   
  然后试了foo=add<int>发现ANSI   C++编译器都正确(但之前的C++编译器说语言错,看来我得好好看一下ANSI   C++标准了)。谢谢各位!  
   
  不过我没有MS上的C++编译器所以无法证实。Top

10 楼CodePage(代码页)回复于 2002-10-10 03:44:35 得分 0

没有在ISO/IEC   14882-1998找到这个问题,在   over.over   里讲了重载函数的地址,还没有找到模版函数地址的章节。  
   
  我还有个不明白:  
   
  template   <class   T>   T   add_t   (T   a,   T   b);  
   
  和  
   
  char       add_o   (char,   char);  
  int         add_o   (int,   int);  
  float     add_o   (float,   float);  
  double   add_o   (double,   double);  
   
  有何区别。  
   
  1,add_o当然是重载,很好理解。而add_t是不是也是重载?  
  2,如果程序中只调用了int   add_t   (int,   int)是不是编译器不产生char   add_t   (char,   char)的代码?而不管是否调用   char   add_o   (char,   char)都产生代码?  
  Top

11 楼do_do(do_do)回复于 2002-10-10 07:20:39 得分 0

1。add_t不叫重载虽然这模板产生的代码的名字处理方法很可能和重载一样。  
  2。对。Top

12 楼CodePage(代码页)回复于 2002-10-10 08:57:15 得分 0

问题已经解决!十分感谢   tianxinet(越来越胖的猴子)   和   do_do(do_do)   的指点。  
   
          看了反汇编,才解决问题。  
   
          pv   =   (int   (*)   (int,   int))add;  
          pv   =   (char   (*)   (char,   char))add;  
          pv   =   (float   (*)   (float,   float))add;  
          pv   =   (double   (*)   (double,   double))add;  
   
          do_do的方案:每个模板函数的每个实例都定义一个类型,虽然可以做强制类型转换,并且运行正确,但类型太多容易引起混淆。  
          tianxinet的方案:每个模板函数再定义返回指针的一个模板函数,运行也正确。但是通过反汇编察看得到如下代码:  
                  //pv   =   fp<int>(&add)  
                  push   offset   add   //地址正确  
                  call   fp  
                  mov   pv,   eax  
                  ......  
                  //在   fp   函数里,只是简单的  
                  mov   eax,   fp  
   
          我觉得最直观的还应该是   pv=Add<int>;   但总是编译出错:“无法解析函数重载”,do_do   您说的“ANSI   C++编译器”是哪个编译器?我听别人说目前还没有完全遵照ANSI   C++标准的编译器。  
   
  还有问题:别扔砖头,我是真的不懂  
  我用的是VC++   7.0,在   typedef   里面不能使用模板,请问这是VC++的限制还是ISO的限制?  
   
  btw:   我一直用c,最近在老伴的压迫之下不得已才学c++(她老显耀java怎么怎么样,我争辩说c++最好,可惜只知皮毛,争不过她。于是就萌发了学透c++的念头,一定要让她心服口服。)现在越学越感到c++的博大精深!我前几天刚来CSDN,还希望大家多多指教。Top

13 楼anrxhzh(百宝箱)回复于 2002-10-10 13:00:55 得分 0

目前的C++标准不支持   template   typedef。  
  详情见:GotW   #79  
  http://www.gotw.ca/gotw/079.htmTop

14 楼do_do(do_do)回复于 2002-10-11 01:00:41 得分 0

我的ANSI   C++编译器是Solaris   CC   5.2,   HP   aCC,   IBM   visualAge。Top

相关问题

  • 模板函数
  • 函数模板
  • friend 模板函数
  • 模板函数的问题
  • 关于函数模板
  • 模板函数问题
  • 关于函数模板
  • 函数模板问题
  • 关于函数模板
  • 成员模板函数

关键词

  • c++
  • vc++
  • 函数
  • 编译器
  • 模板
  • ic
  • 代码
  • template
  • 语法
  • ca

得分解答快速导航

  • 帖主:CodePage
  • do_do
  • tianxinet

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo