最近遇到了该问题,再查找了一些资料后,发现了针对自己问题的解决方法,贴出来让大家一起学习一下。
其实如果这两个问题同时出现,很可能不是链接库缺了lib,而是编译中添加的源没有被实例化,造成编译时,机器以为是缺失lib。本人用的编译器为vs2012,问题出在与,在.h声明了函数后,在.hpp下进行了定义。问题在于.hpp不是其源文件。所以最后生成LNK错误。以前自己移动过,再次添加源文件没注意,造成了.hpp没有被认为是源文件而是头文件。
下面是我看到的一个例子,分享一下。
摘自[1].http://q.cnblogs.com/q/34032/
我在一个头文件里定义了声明了一个模版函数,如下:
//Combination.h
#ifndef VECTOR_H
#define VECTOR_H
#include
#endif
template void Combination(T a[], int len, int index, int m, std::vector& c);
CPP里定义
//Combination.cpp
#include "Combination.h"
using namespace std;
template void Combination(T a[], int len, int index, int m, vector& c)
{
if(0 == m)
{
vector::iterator iter = c.begin();
for(; iter != c.end(); ++iter)
{
cout<<*iter;
}
printf("\n");
return;
}
if(len == index)
return;
c.push_back(a[index]);
Combination(a, len, index + 1, m - 1, c);
c.pop_back();
Combination(a, len, index + 1, m, c);
}
#include
#include "Combination.h"
#ifndef VECTOR_H
#define VECTOR_H
#include
#endif
using namespace std;
void main()
{
int a[] = {1,2,3,4,5,6};
vector c;
Combination(a, sizeof(a) / sizeof(int), 0, 3, c);
system("pause");
return;
}
编译连接时提示以下错误
错误 1 error LNK2019: 无法解析的外部符号 "void __cdecl Combination
错误 2 fatal error LNK1120: 1 个无法解析的外部命令 D:\Documents\Visual Studio 2008\Projects\CppTest\Debug\CppTest.exe CppTest
解决方法:
把方法或类定义放到声明的.h文件中去。
理解这个问题,需要一点编译原理的知识,在调用一个方法或者使用一个类的时候,本cpp作为一个独立的编译单元,可能并不知道某一个方法或者类型的符号是怎么样的,但是这时候不会出错,还是可以针对每个编译单元生成目标文件obj,之后针对没有找到的方法或者类型符号,链接器会在别的obj文件中寻找缺失的符号。
假设模版函数可以放在头文件中声明,CPP中定义,按照你的例子分析一下:
main中调用Combination(a, sizeof(a) / sizeof(int), 0, 3, c);,也就是类型Combination(int, int,int,int, vector&);但是编译器并不知道Combination(int, int,int,int, vector &);,因为这个类型并不在任何一个.h文件中,之后编译器会寄希望于链接器可以解决这个问题,也就是在Combination.cpp的编译目标文件Combination.obj中,但是Combination.obj也没有这个类型,它有的只是一个模板定义。
C++标准里规定: 当一个模板不被用到的时侯它就不该被实例化出来,Combination.cpp没有用到Combination(int, int,int,int, vector&);,所以也就不会编译出来该符号,链接出错也就可以理解了。