模板類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!

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