1、概述
類模版中函數聲明在.h,定義在.cpp中,其他cpp引用引入這個頭文件,會有什么錯誤?
報編譯錯誤:error C2512: 'Demo<int>': no appropriate default constructor available
舉例如下代碼:
demo.h 聲明模版類
template <typename T>
class Demo
{
public:Demo(T value);private:T m_value;
};
demo.cpp
#include "demo.h"template <typename T>
Demo<T>::Demo(T value) : m_value(value)
{
}
main.cpp
#include "demo.h"
int main()
{Demo<int> demo;return 0;
}
2、原因
模版不是在編譯時立即生成代碼,而是在使用時(即實例化時)根據傳入的參數,來生成具體的代碼。
編譯器要看到完整的模版定義,才能生成具體的函數代碼。
如果模版的定義不在當前編譯單元可見,編譯器就不知道如何生成特定類型的實例化模版,就會報編譯錯誤。
如上編譯main.cpp文件時:編譯器會根據demo<int>語句來生成Demo<int>的具體版本,但是模版的定義在demo.cpp文件中,編譯main.cpp時是無法看到的,所以只有聲明,沒有實現,所以報錯了"error C2512: 'Demo<int>': no appropriate default constructor available"
這里有一個問題:為什么普通函數 聲明 和定義分開,編譯就沒有報錯呢?
1、普通函數-?編譯階段
? ? ? 當編譯器編譯一個源文件時,會根據文件中函數的調用去查找函數聲明,如果找到了匹配的聲明,編譯器就認為這個函數存在,并生成一個對外部符號的引用。
2、普通函數-鏈接階段
? ? ? ?(1)、在所有源文件被單獨編譯之后,鏈接器的任務是將所有生成的目標文件(.o 或 .obj 文件)合并成一個可執行文件或庫。
? ? ? ?(2)、鏈接器會解析每個目標文件中的外部符號引用,并嘗試在其他目標文件中找到對應的定義。
? ? ? ?(3)、如果所有被引用的符號都能找到定義,那么鏈接成功;否則,就會出現“未定義的引用”這樣的鏈接錯誤。
3、解決辦法
模版函數的聲明和定義一般需要在一起
學習鏈接:https://github.com/0voice