困扰了我N天的模板问题,NND,总算找到答案了!

  上个星期,不小心用到模板,为了让接口与实现分离,很自然的写了两个.h和.cpp文件。于是一场恶梦引发了 。。。我几乎花了所有课余时间去解决一个看似不可理喻的链接错误。。。。程序大致如下:  

/****************************************
    FileName: zyklist.h
    ModifyTime: 2007.03.17 15:20PM
    Author: ChinaInvent
****************************************
*/


#ifndef ZYK_LIST_H
#define  ZYK_LIST_H

template
< calss T >
class  List
{
    
//.....
public:
   
bool   remove(T& val);
   
//...
}
;

#endif


/*******************************************
    FileName: zyklist.cpp
    ModifyTime: 2007.03.17 15:20PM
    Author: ChinaInvent
*******************************************
*/


#include 
" zyklist.h "
#include 
< iostream >

using   namespace  std;

template
< class  T >
bool  List < T > ::remove(T &  val)
{
   
//....
}




/*******************************************
    FileName: main.cpp
    ModifyTime: 2007.03.17 15:20PM
    Author: ChinaInvent
*******************************************
*/


#include 
< iostream >
#include 
" zyklist.h "
using   namespace  std;

int  main()
{
   List
<int> lst;
   
int a;
   lst.remove(a);   
//链接出错
   return 0;
}

  由于宿舍不能上网,我就一直死磕,总以为是自己的格式有问题。但是,事实证明我太爱死磕了!早上重看《C++对象模型》最后那一章,并未找到答案,但我开始怀疑编译器的问题了。刚才到网上一查,哑然失笑。。。别人早就遇到这个问题啦。。。

  经验:以后有事,还是到网上查查吧。

有一位网友提供了解决方案:

引自:http://guan98413.itpub.net/post/21943/221569

解决方案( 1 ):

采用常用做法,改变程序结构,将模版函数的定义包含在函数声明的头文件中,也就是说将函数声明和定义放在一起。

代码实现如下:

删除Templatetest.cpp文件,将函数的定义和函数声明一起实现。

Templatetest.h

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

#ifndef _TEMPLATETEST_H__

#define  _TEMPLATETEST_H__

#include 

using   namespace  std;


template

inline 
void  print( const  T  & t);

#endif

评论:此方法可行,也是目前常用的方式,缺点是打破了一般规则,很难实现代码隐藏,让人看起来整个程序架构不太清晰。

解决方案(
2 ):

依据C
++ 标准说明,你可以在函数定义前加上 " export " 关键字来做到这一点,但只有少数几个编译器支持这一特性,而且主流的编译器开发商已经明确声明他们无意去实现这一特性。Microsoft声明说,他们不会支持export, 原因如下:要正确地实现这一特性,将带来很多复杂性,而这并未因此带来性能上的提高,AFAIK, gcc 也不支持export。但也有支持这一特性的编译器,采用EDG(Edison Design Group)思想(他们的理念是We  do  our job, you  do  yours, and together we can create some great products)的一些c ++ 编译器就支持export,一些编译器开发商,比如Comeau 和 Intel C ++ 都采用了EDG,但目前好象只有Comeau真正实现了这一点。

代码实现如下:

Templatetest.cpp

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

#include 
" templatetest.h "

template

export 
void  print( const  T  & t)

{

cout 
<< t << endl;

}


评论:此方法正确,但不可行。因为主流编译器基本都不支持export。

解决方案(
3 ):

将Templatetest.cpp函数名改成Templatetest.inl(后缀可以换成别的,但绝对不能是cpp,因为编译器对cpp文件做特殊处理)

将Templatetest.h文件内容改成

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

#ifndef _TEMPLATETEST_H__

#define  _TEMPLATETEST_H__

#include 

using   namespace  std;


template

void  print( const  T  & t);

#include “Templatetest.inl”

#endif

评论:这一方法既能解决unresolved externals问题,又不打破程序结构。唯一的缺陷是函数定义所在文件的后缀有点改动。

综合以上三种解决方案,虽然都能解决unresolved externals问题,但也都存在一些缺陷。具体哪中最合适,笔者认为还要根据开发人员的喜好,根据习惯来决定采用哪种。

参考资料:

C
++  Template Metaprogramming

http:
// www.codecomments.com/

http:
// www.codeguru.com/

http:
// www.velocityreviews.com/

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值