20180330 c++ 學習處理模板化基類裡的名稱
假設我們需要撰寫乙個程式,它能夠傳送資訊到若干不同的公司去,資訊要不譯成密碼,要不就是未經加工的文字,若編譯期間我們有足夠資訊來決定哪乙個資訊傳至哪乙個公司,就可以採用基於模板(template)的解法:
class companya
;class companyb
;... //針對其他公司設計的類
class msginfo; //這個類用來儲存資訊,以備將來產生資訊
template
class msgsender
void sendsecret(const msginfo& info)//類似sendclear(),唯一不同的是這裡呼叫的
//是c.sendencrypted
}這樣的寫法行得通,我們再假設想要在每次送出資訊時記錄(log)某些資訊。派生類可輕易實現這個功能,下面這個解法似乎合情合理:
template
class loggingmagsender:public msgsender
}上述**無法通過編譯,至少對嚴守規律的編譯器而言,這樣的編譯器會抱怨sendclear不存在,但是我明明看到sendclear在父類中啊! 編譯器卻看不到它,這是為什麼呢?
這是因為當編譯器遭遇類模板(class template) loggingmagsender定義式時,並不知道它繼承說明樣的類,當然它繼承的是msgsender,但其中的company是個模板(template)引數,不到後來(當loggingmagsender被具現化)無法確切知道它是什麼,而如果不知道company是什麼,就無法知道 class msgsender看起來像什麼--更確切的說是 沒辦法制導它是否有個sendclear()函式。
為了讓問題更具體化,假設我們有個companyz堅持使用加密通訊:
class companyz //這個類不提供
//sendcleartext函式
;一般性的msgsender template對companyz並不合適,因為那個模板(template)提供了乙個sendclear函式(其中針對其型別引數company呼叫了sendcleartext函式),而這對companyz物件並不合理,欲矯正這個問題,完美可以針對companyz產生乙個msgsender特化版:
tempalte<>
/*乙個全特化的msgsender,它和一般的模板(templated)相同,
差別只在於它刪除了sendclear。
*/class msgsender
};注意:類(class)定義式最前頭的」template<>「語法象徵這既不是模板也不是標準類,而是個特化版的msgsender template,當template的實參是companyz時才被使用,這就是所謂的模板全特化(total template specialization): template msgsender針對型別companyz特化了,而且其特化是全面性的,,也就是說一旦型別引數被定義為companyz,再沒有其他template引數可供變化。
現在,msgsender針對companyz進行了全特化,讓我們再次考慮派生類loggingmagsender:
template
class loggingmagsender:public msgsender
}正如注釋所言,當基類被指定為msgsender時,這段**不合法,因為那個類並未提供sendclear()函式!,這就是c++為何拒絕呼叫的原因:
它知道基類模板有可能被特化,而那個特化版本可能不提供和一般性模板相同的介面,因此它往往拒絕在模板化基類(templatized base class.本例的msgsender)裡尋找繼承而來的名稱(本例的sendclear),就某種意義而言,當我們從物件導向c++跨進模板c++,繼承就不像以前那麼暢通無阻了。
我們重頭再來看,完美必須讓這一行為失效,即: 不進入模板化基類觀察。在這裡有三種方法:
方法一:在基類呼叫動作之前加上「this->」,eg:
template
class loggingmagsender:public msgsender
}方法一:使用using宣告式。
template
class loggingmagsender:public msgsender
}方法一:明白指出被呼叫的函式位於基類裡。
template
class loggingmagsender:public msgsender
}這個方法是最不令人滿意的解法,因為若被呼叫的是虛函式,上述的明確資格修飾(explicit qualification)會關閉 "虛繫結行為"。
注意:可在派生類模板(derived class template)內通過"this->"指涉基類模板(base class template)內的成員名稱,或借由乙個明白寫出的"基類(base class)資源修飾符"完成。
條款43 學習處理模板化基類的名稱
先看程式 class a templateclass drivedusea public usea int main 1.在基類函式呼叫動作之前加上this this useafunc 2.使用using宣告 templateclass drivedusea public usea 3.明確指出被調...
條款43 學習處理模板化基類內的名稱
條款43 學習處理模板化基類內的名稱 know how to access names in templatized base classes.內容 現在我們接到乙個編碼任務,任務要求我們的目標程式能夠傳送資訊到不同的公司去.這裡的資訊可以分為 被譯成密碼的資訊和未經加工資訊明文資訊.我們分析了任務...
43 學習處理模版化基類內的名稱
1 考慮下面的場景,有個類模版templatebox 內部有個方法 現在子類templateclass bigbox public box bigbox內部使用方法 考慮出現什麼問題?2 首先一點,類模版產生出來的類之間,沒有關係。也就是box與box沒有關係。通過指定模版實參,可以產生不同的模板類...