首页新闻找找看学习计划

fatal error LNK1120: 1 个无法解析的外部命令

0
悬赏园豆:10 [待解决问题]

我在一个头文件里定义了声明了一个模版函数,如下

//Combination.h
#ifndef VECTOR_H
#define VECTOR_H

#include <vector>

#endif

template<class T> void Combination(T a[], int len, int index, int m, std::vector<T>& c);


CPP里定义

//Combination.cpp
#include "Combination.h"

using namespace std;

template<class T> void Combination(T a[], int len, int index, int m, vector<T>& c)
{
if(0 == m)
{
vector<T>::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);
}


main中调用

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

#ifndef VECTOR_H
#define VECTOR_H

#include <vector>

#endif

using namespace std;

void main()
{
int a[] = {1,2,3,4,5,6};

vector<int> c;
Combination(a, sizeof(a) / sizeof(int), 0, 3, c);

system("pause");
return;
}

编译连接时提示以下错误

错误 1 error LNK2019: 无法解析的外部符号 "void __cdecl Combination<int>(int * const,int,int,int,class std::vector<int,class std::allocator<int> > &)" (??$Combination@H@@YAXQAHHHHAAV?$vector@HV?$allocator@H@std@@@std@@@Z),该符号在函数 _main 中被引用 main.obj CppTest
错误 2 fatal error LNK1120: 1 个无法解析的外部命令 D:\Documents\Visual Studio 2008\Projects\CppTest\Debug\CppTest.exe CppTest

 

但是,如果把Combination函数的定义直接放在main中,可以通过编译连接并正确运行。请问怎么解决,模版函数不能那样放在头文件中声明,CPP中定义吗

粗暴的香蕉的主页 粗暴的香蕉 | 初学一级 | 园豆:174
提问于:2012-03-30 13:25
< >
分享
所有回答(2)
0

 

理解这个问题,需要一点编译原理的知识,在调用一个方法或者使用一个类的时候,本cpp作为一个独立的编译单元,可能并不知道某一个方法或者类型的符号是怎么样的,但是这时候不会出错,还是可以针对每个编译单元生成目标文件obj,之后针对没有找到的方法或者类型符号,链接器会在别的obj文件中寻找缺失的符号。

 

假设模版函数可以放在头文件中声明,CPP中定义,按照你的例子分析一下:
main中调用Combination(a, sizeof(a) / sizeof(int), 0, 3, c);,也就是类型Combination(int, int,int,int, vector<int>&);但是编译器并不知道Combination(int, int,int,int, vector<int>&);,因为这个类型并不在任何一个.h文件中,之后编译器会寄希望于链接器可以解决这个问题,也就是在Combination.cpp的编译目标文件Combination.obj中,但是Combination.obj也没有这个类型,它有的只是一个模板定义。


C++标准里规定: 当一个模板不被用到的时侯它就不该被实例化出来Combination.cpp没有用到Combination(int, int,int,int, vector<int>&);,所以也就不会编译出来该符号,链接出错也就可以理解了。
zsounder | 园豆:2819 (老鸟四级) | 2012-03-30 13:49

感谢你的回答。

就是说,模版函数只能在使用它的编译单元中定义吗?

那如果同一个模版函数,我会在多个编译单元中使用到,难道要每个编译单元都要定义一次?

像STL里面的那些模版是怎么实现的?使用STL的时候,包含头文件就可以了啊

支持(0) 反对(0) 粗暴的香蕉 | 园豆:174 (初学一级) | 2012-03-30 14:09

@粗暴的香蕉: 你应该去看一下STL的实现,都是在.h文件中完成的,同一个模板函数,在多个编译单元中使用,那么就在头文件中给出声明和实现,有一些编译器是提供export关键字支持分离式编译的,不过并不是所有的编译器都支持。

支持(1) 反对(0) zsounder | 园豆:2819 (老鸟四级) | 2012-03-30 14:17

@Wang Hui: 谢谢你,明白了,我要学习的还有很多,赶快去看一下STL源码才行

支持(0) 反对(0) 粗暴的香蕉 | 园豆:174 (初学一级) | 2012-03-30 14:34
0

将函数的实现放在。h文件中,。这个好像叫做分离编译什么的吧

Rollen Holt | 园豆:210 (菜鸟二级) | 2012-04-12 11:49
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册