.h文件
#pragma once
template<class T>
class Person
{
public:
Person(T age);
void Show();
public:
T age;
};
.cpp文件
#include "Person.h"
template<class T>
Person<T>::Person(T age)
{
this->age = age;
}
template<class T>
void Person<T>::Show()
{
cout << "Age:" << age << endl;
}
main.cpp
#include<iostream>
#include "Person.h"
using namespace std;
int main()
{
Person<int>p(10);
p.Show();
return 0;
}
此时编译出现错误:
错误 1 error LNK2019: 无法解析的外部符号 “public: __thiscall Person::Person(int)” (??0?$Person@H@@QAE@H@Z),该符号在函数 _main 中被引用 \代码\模板类h和cpp分开写\模板类h和cpp分开写.obj 模板类h和cpp分开写
错误 2 error LNK2019: 无法解析的外部符号 “public: void __thiscall Person::Show(void)” (?Show@?$Person@H@@QAEXXZ),该符号在函数 _main 中被引用 \代码\模板类h和cpp分开写\模板类h和cpp分开写.obj 模板类h和cpp分开写
错误 3 error LNK1120: 2 个无法解析的外部命令\代码\test01\Debug\模板类h和cpp分开写.exe 1 1 模板类h和cpp分开写
而注释掉Personp(10);p.Show();后编译成功
问题分析:
这和c++编译机制和模板实现机制有关。
c++是独立编译,例如a.cpp、b.cpp、c.cpp三个文件,先独立编译成三个独立的目标文件,即a.o、b.o、c.o,然后再通过链接器链接起来,生成可执行文件。
在编译时,a.cpp发现一个函数调用,在当前文件找不到函数定义,则在函数位置生成符号,在链接时,再寻找这个函数。
模板是两次编译。第一次编译时只对模板进行编译,不生成具体函数,在调用时才生成具体函数。
所以在这个项目中,编译main.cpp时,会编译Person.h,而Person.h里只有函数声明,不进行编译。则在链接器寻找函数时,因为寻找不到函数出现错误。而Person.cpp编译时,函数模板只进行第一次编译,因为没有具体使用,所以没有进行第二次编译,没有生成具体函数。所以在main.cpp链接时,因为寻找不到函数出现错误。
改正:
在main.cpp中将#include “Person.h”替换为#include “Person.cpp”.
所以在写类模板时,声明和定义写在一个文件里。文件后缀为hpp!