woaidongmao

文章均收录自他人博客,但不喜标题前加-[转贴],因其丑陋,见谅!~
随笔 - 1469, 文章 - 0, 评论 - 661, 引用 - 0
数据加载中……

模板导致的代码膨胀问题和解决

模板是一种源码复用技术,在某些情况下使用它可以使代码看起来非常优雅,著名的boost库就是模板发扬的典范.
然而模板也存在弊端,大量使用模板可能导致代码膨胀.下面介绍一种解决的方案:

我们首先看一段一般代码:

clip_image001template < typename T >
clip_image001
class  Vector
clip_image002clip_image003 {
clip_image004
public :
clip_image004    
virtual   void  Say()
clip_image005clip_image006     {
clip_image004        
const  type_info &     t  =  typeid(T);
clip_image004        std::cout  <<   " Vector< "   <<  t.name()  <<   " >::Hello "   <<  std::endl;
clip_image007    }
clip_image008} ;
clip_image001
clip_image001
//  特例化
clip_image001
template <>
clip_image001
class   Vector < void *>
clip_image002clip_image003 {
clip_image004
public :
clip_image004    
virtual   void  Say()
clip_image005clip_image006     {
clip_image004        std::cout  <<   " Vector<void*>::Hello "   <<  std::endl;
clip_image007    }
clip_image008} ;
clip_image001
clip_image001
int  _tmain( int  argc, _TCHAR *  argv[])
clip_image002clip_image003 {
clip_image004    Vector <
int *>     pIntVec;
clip_image004    pIntVec.Say();
clip_image004    Vector <
double *>     pDoubleVec;
clip_image004    pDoubleVec.Say();
clip_image004    
return   0 ;
clip_image008}


输出:
Vector<int *>::Hello
Vector<double *>::Hello
从这里,我们可以看出程序在运行的过程中生产了两分Vector的代码(int*double*),尽管这里有特例化,然而类型不匹配,编译器在编译过程中无法定位到特例化版本.如果这个Vector被滥用,即使是一个中等规模的程序也可能耗费成兆字节的代码控件.

我们必须寻找一种中间桥梁使编译器在编译过程中定位到void*的特例化版本.按照模板选择策略,编译器总是选择最特例化的模板,我们可以通过一个中间的模板联系起上面两个版本的模板.下面看一段代码:

clip_image001template < typename T >
clip_image001
class  Vector
clip_image002clip_image003 {
clip_image004
public :
clip_image004    
virtual   void  Say()
clip_image005clip_image006     {
clip_image004        std::cout  <<   " Vector::Hello "   <<  std::endl;
clip_image007    }
clip_image008} ;
clip_image001
clip_image001
//  特例化
clip_image001
template <>
clip_image001
class   Vector < void *>
clip_image002clip_image003 {
clip_image004
public :
clip_image004    
virtual   void  Say()
clip_image005clip_image006     {
clip_image004        std::cout  <<   " Vector<void*>::Hello "   <<  std::endl;
clip_image007    }
clip_image008} ;
clip_image001
clip_image001
//  特例化
clip_image001
template < typename T >
clip_image001
class  Vector < T *>  :  public  Vector < void *>
clip_image002clip_image003 {
clip_image008} ;
clip_image001
clip_image001
int  _tmain( int  argc, _TCHAR *  argv[])
clip_image002clip_image003 {
clip_image004    Vector <
int *>     pIntVec;
clip_image004    pIntVec.Say();
clip_image004    Vector <
double *>     pDoubleVec;
clip_image004    pDoubleVec.Say();
clip_image004    
return   0 ;
clip_image008}

输出:
Vector<void*>::Hello
Vector<void*>::Hello
从这里,我们可以看出程序在运行过程中全部使用Vector<void*>的版本.class Vector<T*>模板便是关键的环节.编译器在编译过程中,由于class Vector<T*>class Vector更特例化,所以遇到Vector<int*>Vector<double*>时都选择class Vector<T*>,class Vector<T*>继承Vector<void*>,一个更加特例化版本,所以编译器不再产生新的模板而采用 Vector<void*>这个最特例化版本,这样所有指针模板都归结到Vector<void*>,class Vector<T*>为用户提供了一个精美而且安全的界面,Vector<void*>作为底层实现细节被隐藏.

 

posted on 2009-08-26 13:27 肥仔 阅读(3427) 评论(2)  编辑 收藏 引用 所属分类: C++ 模板

评论

# re: 模板导致的代码膨胀问题和解决  回复  更多评论   

嗯,在The C++ Programming 看到过这内容
2010-05-20 22:30 | 小时候可靓了

# re: 模板导致的代码膨胀问题和解决  回复  更多评论   

int double 本来就和void特列的实现方式不一样,这个和代码膨胀有什么关系?如果按照你的第二种来解释,岂不是所有的数据类型都输出Vector<void*>::Hello,那么要输出Vector<int *>::Hello怎么解决?模板只是简化代码,也即是同一份逻辑使用同一个模板进行推导,避免同样的工作重复N次吗,减轻人工敲代码的工作而已,而事实上模板要做的事和你想实现的功能是一一对应的,不用模板就得换成码农一行一行到敲!模板模板,望文生义也知道他就是个模具,别理解偏了!
2015-08-27 16:10 | myanbu

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理