模板例項化
我一直在尋找一些可以寫一篇小文章的東西
這似乎是個不錯的選擇。
論壇上有很多關於這個問題的帖子,作者將
模板拆分為 *.h 檔案和 *.cpp 檔案,並遇到連結器
問題。
通常給出的答案是將所有模板內容放入 *.h 檔案中
因為必須這樣做。
類/函式。
這並不完全正確。
C++ 有隱式模板例項化和顯式例項化
隱式例項化
在
template.h 中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
#ifndef TEMPLATE_H
#define TEMPLATE_H
#include <iostream>
template <typename T>
class myTemplate
{
private:
T data;
public:
myTemplate();
myTemplate(T t);
T getData() const;
void displayData() const;
static int someValue;
};
template<typename T>
myTemplate<T>::myTemplate()
:data()
{
}
template<typename T>
myTemplate<T>::myTemplate(T t)
:data(t)
{
}
template <typename T>
T myTemplate<T>::getData() const
{
return data;
}
template <typename T>
void myTemplate<T>::displayData() const
{
std::cout << data <<std::endl;
}
template<typename T>
int myTemplate<T>::someValue = 100;
#endif
|
在 main.cpp 中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
#include <iostream>
#include "template.h"
using namespace std;
int main()
{
myTemplate<int> myTi(5);
myTi.displayData();
myTemplate<float> myTf(3.5f);
myTf.displayData();
return 0;
}
|
在上面的示例中,完整的模板定義位於標頭檔案中
main.cpp 包含該標頭檔案 - 因此在編譯
和連結過程中不會出現問題。
如果我們忘記定義
displayData() 函式
那麼我們會收到連結器錯誤,而不是編譯器錯誤。
//=========================================================================================//
顯式例項化 假設我們要將模板類拆分為標頭檔案和原始檔。
所以我們有 main.cpp 和 template.cpp。
我們編譯這兩個檔案,但會收到連結器錯誤,因為 template.cpp
檔案中的實際程式碼未被例項化。
要使編譯器例項化所需的程式碼,我們可以使用顯式例項化。
template.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
#ifndef TEMPLATE_H
#define TEMPLATE_H
#include <iostream>
template <typename T>
class myTemplate
{
private:
T data;
public:
myTemplate();
myTemplate(T t);
T getData() const;
void displayData() const;
static int someValue;
};
#endif
|
template.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
#include "template.h"
#include <iostream>
//template functions
template<typename T>
myTemplate<T>::myTemplate()
:data()
{
}
template<typename T>
myTemplate<T>::myTemplate(T t)
:data(t)
{
}
template <typename T>
T myTemplate<T>::getData() const
{
return data;
}
template <typename T>
void myTemplate<T>::displayData() const
{
std::cout << data <<std::endl;
}
template<typename T>
int myTemplate<T>::someValue = 100;
//The explicit instantiation part
template class myTemplate<int>;
template class myTemplate<float>;
|
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
#include <iostream>
#include "template.h"
using namespace std;
int main()
{
myTemplate<int> myTi(5);
myTi.displayData();
myTemplate<float> myTf(3.5f);
myTf.displayData();
return 0;
}
|
重要的部分是
template.cpp 中的最後幾行。我們知道我們需要一個
myTemplate<int> 和一個
myTemplate<float>,因此我們顯式地要求編譯器為這些
兩種類型別的所有的可例項化部分生成程式碼。
請注意例項化指令的編寫方式。
我們現在可以成功地編譯和連結我們的程式碼。
我們還可以顯式地例項化模板函式,或單個模板類成員函式。