C++中模板不能把实现和声明放在两个不同的文件下

http://zhidao.baidu.com/question/322405048.html

http://www.zhihu.com/question/20630104

http://bbs.chinaunix.net/thread-923716-1-1.html

在Fraction.h中,我是这么定义的
#pragma once
#ifndef FRACTION
#define FRACTION
template<class T>
class Fraction
{
public:
Fraction(void);
Fraction(T ,T);
~Fraction(void);
private:
T numerator;//分子
T denominator;//分母
};
#endif
在Fraction.cpp中我是这么实现的
#include "StdAfx.h"
#include "Fraction.h"

template<class T>
Fraction<T>::Fraction(void):numerator(0),denominator(0)
{
}

template<class T>
Fraction<T>::Fraction(T numerator,T denominator)
{
this->numerator=numerator;//分子
this->denominator=denominator;//分母
}

template<class T>
Fraction<T>::~Fraction(void)
{
}

主函数调用如下
#include "stdafx.h"
#include"Fraction.h"

int _tmain(int argc, _TCHAR* argv[])
{
Fraction<int> ftion(10,120);
return 0;
}

提示如下错误
1>One.obj : error LNK2019: unresolved external symbol "public: __thiscall Fraction<int>::~Fraction<int>(void)" (??1?$Fraction@H@@QAE@XZ) referenced in function _wmain
1>One.obj : error LNK2019: unresolved external symbol "public: __thiscall Fraction<int>::Fraction<int>(int,int)" (??0?$Fraction@H@@QAE@HH@Z) referenced in function _wmain
1>F:\DataStruct\ChapterOne\One\Debug\One.exe : fatal error LNK1120: 2 unresolved externals
1>Build log was saved at "file://f:\DataStruct\ChapterOne\One\One\Debug\BuildLog.htm"
1>One - 3 error(s), 0 warning(s)

 两个解决方案:
①将Fraction.h和Fraction.cpp文件写到一个文件中,即Fraction.h头文件。
②将Fraction.cpp改名为Fraction.template文件,然后再Fraction.h倒数第一行#endif之前加入一行代码 #include "Fraction.template"即可。 

这个是初学者常见问题了。

简而言之,目前绝大多数C++编译器不支持将模版类/模版函数的声明与实现分开。
所以你要写就全部一起写在头文件中,不要分开写到两个文件中。或者像楼上所说在头文件中再#include一次(不过没啥意义)。

这个是C++的一个老顽固问题了,虽然C++标准有规定通过export关键字来实现模版的分离编译,但是因为实现过于复杂,实际上几乎没有编译器鸟它。VC、BC、GCC都不支持。(貌似只有ICC部分支持)

所以你也只能向现实妥协了呵呵,就像STL一样,把模版函数和模版类的实现全部写在.h头文件中吧。

@欲三更 邀,这个问题让我想起我在实习的时候犯的一个错误,就是把模版类的定义和实现分开写了,结果编译出错,查了两天才查出问题。

C++ 中每一个对象所占用的空间大小,是在编译的时候就确定的,在模板类没有真正的被使用之前,编译器是无法知道,模板类中使用模板类型的对象的所占用的空间的 大小的。只有模板被真正使用的时候,编译器才知道,模板套用的是什么类型,应该分配多少空间。这也就是模板类为什么只是称之为模板,而不是泛型的缘故。

既 然是在编译的时候,根据套用的不同类型进行编译,那么,套用不同类型的模板类实际上就是两个不同的类型,也就是说,stack<int>和 stack<char>是两个不同的数据类型,他们共同的成员函数也不是同一个函数,只不过具有相似的功能罢了。如 上图所示,很简短的六行代码,用的是STL里面的stack,stack<int>和stack<char>的默认构造函数和 push函数的入口地址是不一样的,而不同的stack<int>对象相同的函数入口地址是一样的,这个也反映了模板类在套用不同类型以后, 会被编译出不同代码的现象。

所以模板类的实现,脱离具体的使用,是无法单独的编译的;把声明和实现分开的做法也是不可取的,必须把实现全部写在头文件里面。为了清晰,实现可以不写在class后面的花括号里面,可以写在class的外面。

另外提供一些参考:
stackoverflow.com/question

目前大部分的C++编译器要求把模版的定义和实现都放在头文件中,而不能支持分开编译的方式。
C++标准中有一个export关键来解决这个问题,但现在大部份的编译器并不能支持它。

原文地址:https://www.cnblogs.com/androidme/p/2900241.html