将模板类的声明和实现分别放在不同的文件中

参考:
http://www.cs.technion.ac.il/users/yechiel/c+±faq/templates-defn-vs-decl.html
https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file

如果像一般函数那样处理,简单地将模板声明、定义分别放在 .h 和 .cpp 文件中,会报错“无法解析的外部命令”。



错误原因


3个前提:

  1. 模板不是类或函数,模板是编译器用来生成一系列(a family of)类或函数的模式(pattern)。
  2. 编译器为了生成特定代码,它必须知道模板的定义、声明,以及特定的、用于“填充模板中待定类型”的具体类型。
    例如,为了使用 Foo<int>,编译器必须同时“看到”Foo模板和 Foo<int>.
  3. 编译器在编译一个cpp文件时,不了解另一个cpp文件里的情况。

例子:

//Foo.h
template<typename T>
class Foo 
{
private:
 	T x;
public:
	 Foo();
	 void someMethod(T x);

};

//Foo.cpp
template<typename T>
Foo<T>::Foo()
{
 	...
}
template<typename T>
void Foo<T>::someMethod(T x)
{
 	...
}

// Bar.cpp
void blah_blah_blah()
{
	...
 	Foo<int> f;
 	f.someMethod(5);
 	...
}
  • 在Foo.cpp中编译器只看到模板,不知道该用什么类型来填充“T”。
  • 在 Bar.cpp中,编译器只看到它需要创建一个Foo<int>,但是看不到模板,不知道如何生成代码。

综上所述,编译器无法同时看到Foo模板和Foo<int>实例,所以无法生成函数 Foo<int>::someMethod()


所以说,“将模板声明和定义放在一起”,实际上是为了达成 “编译器能同时“看到”生成代码的模板和用于填充模板的具体类型” 这一目的。



解决方法

  1. 创建一个同名的.tpp后缀文件,将模板类的实现放入其中,然后在同名.h文件末尾#include。
    代码:
//Foo.tpp
template <typename T>
void Foo<T>::doSomething(T param)
{
    //implementation
}

//Foo.h
template <typename T>
struct Foo
{
    void doSomething(T param);
};
#include "Foo.tpp"

原文中的回答没有提到“.tpp”后缀的意义,这里我认为是为了能使文件命名一致而使用的后缀,起到的作用和.h一样。

  1. 在.cpp文件中加上具体的类型
    代码:
// implementation of Foo's methods

// explicit instantiations
template class Foo<int>;
template class Foo<float>;
// You will only be able to use Foo with int or float

这种方法为模板的使用加上了限制,只能使用 int 和 float 实现 Foo 模板类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值