不得不鄙视一下VC++

作者在 2007-12-15 19:40:05 发布以下内容

摘要(正文的废话太多,不想浪费时间可以不看)

VC中使用类模板,如果类的成员函数声明和定义分别放在.h和.cpp文件中,连接的时候会报错如下:

1.obj : error LNK2001: unresolved external symbol "public: void __thiscall node<int>::display(void)" (?display@?$node@H@@QAEXXZ)
Debug/1.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

1.exe - 2 error(s), 0 warning(s)

解决办法:

方法一:不要分成两个文件,把成员函数的声明和定义都放在.h文件里面

方法二:如果你确定的知道这个模板只会被用成那些类型,可以在.cpp文件的末尾加上template class 类名<可能的类型>;
比如写了一个节点类node,只可能用在int和double类型,那么在.cpp文件最后加上如下语句:
template class node<int>;
template class node<double>;
如果还有其他类型,每种类型必须添加一句

推荐使用第一种方法.

=======================以下为正文======================

为了VC++本身的一个不足,我居然浪费了2天的时间!

背景:

最近突然兴趣高涨,啃起了数据结构,本来作为编程的一门基本功,数据结构这门课应该早就学过了,可惜咱不是正宗的计算机系出身,本来的专业跟计算机那差的可不是一般的远.对计算机的学习纯粹是兴趣使然,所以学习的方向也就是随心所欲,没有系统的学习,也没有人指点.还好现在的网络实在是发达,各种XX教程多如牛毛上的细胞,所以目前的水平自认为还是可以的(呃,可以糊弄那些没学过编程的).最近终于对数据结构提起兴趣,那就赶快学起来,这块不学始终是不行的,于是看起了北大的张铭老师的视频教程,个人评价是讲的还行(如果不是太困的话不会睡着),不过因为课时的限制,有些地方讲的太简略.

起因:

教程已经看到了图,根据多年自学编程的经验,光看教程是绝对不可能学会的,编程这东西,肯定要在实践中才能真正学到东西,光听别人讲或者光看书,那太简单了,等到自己编起来才会发现问题多的很.

经过:

于是开始练习,第一个目标当然是最简单的单链表了(MS这个都算不上是数据结构了).经过仔细的考虑,最终决定使用C++来实现,"类"是一个好东西,不用浪费了.IDE选择了VC6,我还是比较喜欢VC的,调试功能比较完善.

新建工程,添加一个node类,VC还自动生成了两个文件node.h和node.cpp,构造和析构函数也都写好了,还有node.h前面的防止重入也写好了,的确不错.

因为以前还没真正编过C++的东西,大大小小的错误一堆,不过还是在我超强的DEBUG能力下,一一解决,最后程序如下:

// node.h: interface for the node class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_NODE_H__AA536975_5993_483D_BA04_BEBC765ADF87__INCLUDED_)
#define AFX_NODE_H__AA536975_5993_483D_BA04_BEBC765ADF87__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <iostream.h>
template<typename T>
class node
{
private:
 T _value;
 node *_next;
public:
 node(T value,node* next)
 {
  _value=value;
  _next=next;
 }
 node(T value)
 {
  _value=value;
  _next=NULL;
 }
 node()
 {
  _value=0;
  _next=NULL;
 }
 void display(void);
 virtual ~node(){}
};
#endif // !defined(AFX_NODE_H__AA536975_5993_483D_BA04_BEBC765ADF87__INCLUDED_)

// node.cpp: implementation of the node class.
//
//////////////////////////////////////////////////////////////////////

#include "node.h"
template<class T>
void node<T>::display()
{
 cout<<"Value="<<_value<<" Next="<<_next<<" This="<<this<<endl;
}

然后写了一个main函数测试,内容太简单就不写了.测试结果link的时候提示2个error

1.obj : error LNK2001: unresolved external symbol "public: void __thiscall node<int>::display(void)" (?display@?$node@H@@QAEXXZ)
Debug/1.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

1.exe - 2 error(s), 0 warning(s)

这次我就不行了,怎么弄都解决不了这个错误.那只能开始找资料,百度上搜了半天,又找了C++ Primer第3版和第5版,找了关于template的介绍,甚至还找了stl的源码,找了候捷老师的<STL源码剖析>.最终的结论是,这样写没错..........

最后没办法,还是靠百度,搜索template unresolved external symbol,终于明白了错误所在

原来是VC本身的原因,对于这种使用类模板,又把成员函数的声明和定义分别放在.h和.cpp文件中的情况,VC没办法智能的找到模板的定义,导致他认为两个文件中的声明和定义不一致.

解决的办法有两种,一是全部定义的放在.h文件中,二是在.cpp文件最后加上template class 类名<可能的类型>;
比如我们的node类模板,可能会被用成int和double,那么就要写两句
template class node<int>;
template class node<double>;
如果还有更多的可能,就要每种可能再写一行.

结果:

第二种解决方法显然不能使用,简单变量类型还好说,要是以后有自定义的类,那还要修改这个地方,而且到时候还不一定他能认识.

那只能用第一种了,把所有的定义写在.h文件里面.其实stl里面也是这么干的.

后记:

问题终于解决,两天来的郁闷也终于过去了,万里长征已经踏出了第一步,后面的路还很长很长..........

最后BS一下VC...........

原创 | 阅读 3146 次
文章评论,共1条
永夜的极光(作者)
2008-02-15 08:28
1
不是VC的问题那是谁的问题呢?麻烦具体说说
游客请输入验证码