模板类h和cpp分开写问题浅析

.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!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章