2017年4月4日 星期二

template實例化和typedef用法

http://stackoverflow.com/questions/115703/storing-c-template-function-definitions-in-a-cpp-file
http://www.codeproject.com/Articles/48575/How-to-define-a-template-class-in-a-h-file-and-imp
主要是參考上面兩篇,其中第二篇的方法3才是我要用的方法

先說想法,我們知道template可以省掉非常多的寫Code量,舉例來說,我們生成一個不同類型的Point,也就是XY值,假設您要生成有char類型的,short int類型的,int類型的或是double類型的結構,

您看這樣就要寫四份相似的class,替每個結構弄一個class,新增一個function要改每份一次,修改一個function每份也要調一次,真的會累死

註:至於點為什麼要那麼多類型,因為您會發現vcl元件mouse move時的XY是int,但是您會發現您在做影像處理運算時,點的類型要用double,因為您要直接用點做運算

這樣其實Coding量會很大,因此使用Template可以減少Coding量,上面的問題您只要寫一個template class就可以完成了,看這個之前,我當作您已經知道template再幹嘛了,因為我這裡不是要講template怎麼用,而是要講其他問題

如此使用template可以減少工作量,這不是很好嗎,但是衍伸問題

Template實作只能寫在.h中,這會造成我們要是要修改template的東西時,會一直修改.h檔,導致編譯時有include到這個檔案的會跟著重新編譯,導致編譯時間變長,要是您這個東西很常用,您會發現您常常要要同時編譯很多.cpp檔,程式才可以Link

這不是一個好做法,因此我們就會想有沒有辦法能將實作的地方改到.cpp檔呢

其實就是template實例化(template instantiation)

假設我們做出template,這是一般寫法
point.h
template <typename T>
struct hahaha_point
{
public:
T x_;
T y_;
public:
hahaha_point(){}
~hahaha_point(){}
Void function(){};
};


您會發現上面的函式都必須在.h修改,不然compiler完會Link不到東西,例如下面這樣
point.h
template <typename T>
struct hahaha_point
{
public:
T x_;
T y_;
public:
hahaha_point();
~hahaha_point();
Void function();
};

Point.cpp
template <typename T>
hahaha_point<T>::hahaha_point()
{
x_ = 0;
y_ = 0;
}

template <typename T>
hahaha_point<T>::~hahaha_point()
{
}

template <typename T>
void hahaha_point<T>::function()
{
}


當您有使用到上面的函數時,例如function,會找不到function(unresolved external)
因此我們在.cpp最後面加入下面(記得一定要寫在同一個.cpp,不然一樣unresolved external)
template class hahaha_point<int>;
template class hahaha_point<float>;
template class hahaha_point<double>;


這樣就完成了,往後您在使用時,如下

Hahaha_point<int> a;
a.function();
就不會發生unresolved external的問題了

而且最重要的是,您要修改實作內容,例如改function的內容,只要在.cpp更改,會比較方便,不會案子做大了一直編譯一直改,很累的:D

附帶一提,為了方便可以將template的類型在.h定義
typedef hahaha_point<int> __POINT_32S;
typedef hahaha_point<float> __POINT_32F;
typedef hahaha_point<double> __POINT_64F;

typedef __POINT_32S POINT_I;
typedef __POINT_32F POINT_F;
typedef __POINT_64F POINT_D;


這樣往後您就可以用比較短的字做宣告,例如
POINT_I pt;
Pt.function();

方便吧,

雖然您使用一種新類型要template實例化一種,但是只需做一次,往後改時還是比較方便的

沒有留言:

張貼留言