c++使用模板时.h和.cpp分离产生的问题分析和解决方案

首先需要认知以下几点 :


  1. 编译器只编译cpp文件,不单独编译.h文件
  2. 编译器在编译阶段是独立编译的
  3. 编译一个cpp文件时,展开包含的头文件,发现一个调用在当前文件无法找到,就标记为一个符号
  4. 类模板产生的符号跟该模板的任何具体类的符号都不同

代码:


假设三个文件分别是Temp.h Temp.cpp main.cpp(我们举最简单的栗子以方便理解)

//Temp.h
template<typename Type>
class CTemp
{
    CTemp();
};
//Temp.cpp
#include "Temp.h"
template<typename Type>
CTemp<Type>::CTemp()
{
}
//main.cpp
#include <iostream>
using namespace std;
#pragma warning(disable:4996)
#include "Temp.h"
int main()
{
    CTemp<int> a;
    return 0;
}

编译后报错如下:
这里写图片描述

分析:


在编译Temp.cpp时,模板的构造被导出符号我们假设为a1,在编译main.cpp时,我们根据模板定义一个具体类的对象,但是即使展开了头文件,我们还是找不到构造的定义,就在这里标记一个导入符号a2(表示我们需要在链接阶段导入一个符号a2才能运行).

编译阶段结束了,我们要进行最后的阶段链接了,凡是需要导入符号的,都要找到这个符号,将真正的调用导入才行.结果找了半天,发现没有跟a2相匹配的符号,就报错说,无法解析这个外部的符号

解决方案:


  • 在.cpp文件中使用类模板显式实例化
template CTemp<int>; 
  • 在main函数中包含”Temp.cpp”文件,一般改名为”Temp.hpp”,来表示是一个头文件形式的cpp文件(很绕)
  • .h文件和.cpp文件写在一起
  • 在.cpp文件中随便写个函数中使用了CTemp模板类就会提供一个导出符号a1
// 在Temp.cpp中任意位置加上这句
void Func()
{
    CTemp<int> temp;
}

版权声明:本文为saodilaoshu原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。