比如說有這樣乙個類的繼承體系:類cderiveda和cderivedb都繼承自類cbase。如果要寫乙個函式傳入上面類中的乙個物件的引用,在函式裡面我們要根據物件的型別來進行相應的處理,也就是說對不同型別的物件進行不同的處理。在這種情況下我們就需要類的物件中儲存有型別資訊。下面就用乙個簡單的例子來說明怎麼讓自己編寫的類有型別資訊。
首先,根據類的繼承關係建立型別資訊tag:
struct lx_base_tag {};
struct lx_deriveda_tag : public lx_base_tag {};
struct lx_derivedb_tag : public lx_base_tag {};
然後,建立乙個型別特徵結構:
template
struct category_traits ;
最後,在每個類裡面加上型別資訊:
// 為了簡單起見,這裡的類沒有實際內容,只儲存型別資訊
class cbase ;
class cderiveda : public cbase ;
class cderivedb : public cbase ;
這樣,我們就可以在函式中根據物件型別的不同進行不同的處理:
// 為了簡單起見,這裡不同的處理僅僅為輸出不同的字串
template
void test(t &t)
上面的函式雖然實現了想要的功能,但是卻不是最優方案。
根據模板的特性,在上面的例子中型別t在編譯期就已經確定。但是,if語句的判斷卻是在執行期進行判斷的。如果出現下面的**,那麼test就會生成兩個副本。
cderiveda a;
testa(a);
cderiveda b;
test(b);
這樣就會造成編譯出的可執行檔案膨脹,而且typeid在執行期對效率也有一定的的影響。
那麼有沒有什麼方法使得在編譯期就能根據物件型別的不同而將不同的處理方法編譯進可執行檔案呢?當然有,那就是函式過載。函式過載的作用就是根據引數型別的不同而呼叫不同的函式。所以,可以引入乙個過載的幫助函式:
// 為了簡單起見,這裡不同的處理僅僅為輸出不同的字串
template
void dotest(t &t, lx_deriveda_tag)
template
void dotest(t &t, lx_derivedb_tag)
而真正的函式只要呼叫這個幫助函式就行了:
template
void test(t &t)
這樣,在編譯期,所有的型別都確定了,而且根據型別的不同編譯器會選擇不同的函式編譯進可執行檔案中。
通過這種方法,既不會造成編譯出的可執行檔案膨脹,也避免了typeid在執行期對效率的影響。
2023年10月6日更新:
國慶節前參加了公司組織的stl的高階培訓,主講人就是大名鼎鼎的侯捷。他是《stl原始碼分析》的作者,而這次主講的內容也是對stl原始碼的分析。對我來說這也是第一次比較深入的學習stl的原始碼。而本文中所講的其實就是stl裡面的traits。stl原始碼中到處都能看到traits的身影,這也是實現編譯期函式過載的有效方法。
下面對文中的最後一段**進行一下解釋:
1.在編譯的時候t的型別已經確定;
2.**typename category_traits::category()其實就是建立乙個型別為t::category的臨時變數;
3.編譯期根據上面的那個變數可以推導出這個變數的型別(lx_base_tag,lx_deriveda_tag,lx_derivedb_tag);
4.通過上面的型別就可以判斷呼叫哪個函式。
經過上面的幾步,就實現了編譯期的函式過載。
另外,對上面2中**裡的typename關鍵字做乙個說明:如果僅僅看category_traits::category這樣的**的話,是分辨不出category是什麼的(有可能是乙個靜態變數),加上typename關鍵字就是明確的告訴編譯器這是乙個型別。
讓你編寫的類也有型別資訊
比如說有這樣乙個類的繼承體系 類cderiveda和cderivedb都繼承自類cbase。如果要寫乙個函式傳入上面類中的乙個物件的引用,在函式裡面我們要根據物件的型別來進行相應的處理,也就是說對不同型別的物件進行不同的處理。在這種情況下我們就需要類的物件中儲存有型別資訊。下面就用乙個簡單的例子來說...
讓你也有百萬富翁的生活
呵呵,百萬富翁的地位.和許多難以捉摸的夢想神奇的數字。你可曾採取了停下來想一想你如何能達到這個收入水平?我有。由於事實上,我只是對我的老闆解雇乙個月前,為了追求我的夢想的生活方式和銀行帳戶。乙個百萬富翁的銀行帳戶。它需要幾個因素來達到這個百萬富翁的生活方式,你走之前,我想一些錢瘋狂螺母的工作,我不只...
小知識 讓你的DLL類庫帶上注釋
在我們進行開發公用元件時,一般會把dll給團隊的開發人員直接使用,而不會把專案給他們,因為那樣對為框架級 是不安全的,這時引用框架類庫有兩種方式,一種是直接複製dll,第一種是使用包管理工具nuget,當然我比較提倡第二種,因為當你的包有更新時,使用第二種可以很方法的指公升級你的dll!在生成dll...