C++中如何将 template 模板类(模板函数)的 声明和定义分别写在两个文件中.

我们正常使用模板的时候都是将声明和定义放在一起.

  • 这里要注意的是 模板不是一种数据类型! 他既不是函数也不是类,他是生成这两者的 “模板”!这个概念可能有点绕, 举例来说: 我有一张
    设计图(template), 这个设计图是用来制作板凳的.
    那么光有这张设计图,我是没法使用的.我需要有材料,或者说指定用什么材料去做板凳,比如我要用木头或者用塑料之类的.当我有了这些材料之后,再按照图纸去制作出了板凳才能真正被使用.
  • 到这里再说说编译器对于模板的处理. 编译器看到模板之后,就比如是一名木匠看到了图纸,光看到图纸的话 木匠是什么都做不了的.他只能等到别人要求他制作板凳,并且告诉他需要用什么材料去做,才会真的动手去生产出一个板凳.

下面看一个实际的例子:
你现在要为别人提供一个库, 那么常用的做法是

  1. 写一个头文件,将函数定义放在这里.
  2. 写一个源文件 包含头文件,将实现放在这里. 因为你并不想要别人知道怎么实现的,只要知道怎么用就行了.
  3. 将他编译成 静态库或者动态库 提供给别人使用.

但是现在问题来了,头文件里有一个 模板函数!
类似如下:

//foo.h
#pragma once
template <class T>
void print(T t);
//foo.cpp
#include "foo.h"
#include 
using namespace std;
template <class T>
void print(T t){
	cout << "Hi,"<<t << endl;
}
//main.cpp
//这里通过链接库的方式使用函数 print. 
#include "foo.h"
int main(int argc, char** argv){
	print<int>(3);
	return 0
}

到这里看着好像没有问题. 那么回想一下我们刚刚举得例子, 木匠(编译器) 拿到了图纸(print函数的模板),想要将他变成一个 凳子(动态库或者静态库) 给别人使用.
我们是不是缺少了什么?
对! 我们缺了材料! 我不知道别人需要什么材料!
那么这个时候我们的动态库里保存了什么呢? 什么也没有! 因为我们不知道生成什么类型的凳子!
对应编译器的错误就是 undefined reference!

那么我们有什么办法解决这个问题呢? 本文提供两种方法:

  1. 我将 foo.cpp 内容添加到 foo.h中 变成了,这样 main.cpp中就知道了 模板的声明和定义. 可以自己生成一个 “凳子”. 但是这就违背了我们生成库的初衷. 别人已经知道了我们的实现!
  2. foo.cpp修改为
//foo.cpp
#include "foo.h"
#include 
using namespace std;
template <class T>
void print(T t){
	cout << "Hi,"<<t << endl;
}
template void print<int>(int);

这样做相当于,我提前告诉木匠 要做一个"int"类型的凳子. 这样库里就包含了这个凳子. 别人可以拿过去直接用.
这样做也有一个坏处. 因为你不知道别人想要用什么凳子. 你就得准备"float" “double” "char"各种类型的凳子了…

更多关于模板的问题可以参考这里:
FAQ about template in c++

你可能感兴趣的:(c++扩展)