條款43 學習處理模版化基類內的名稱

2021-06-29 09:57:38 字數 2212 閱讀 9791

考慮以下**,功能為傳送不同資訊至不同部門,採用模版方法。

class companya

;class companyb

;….. //其他公司的類

class msginfo;    //用來儲存資訊,以備用

templateclass msgsend

void sendsecret(const msginfo& info) //格式同上

}

現在我們需要在傳送資訊前記錄日誌,我們可以很容易派生出來

templateclass logmsgsend : public msgsend

};

我們注意到這個派生類的資訊傳送函式有乙個不同的名稱(sendclearmsg),與其基類中的(sendclear)不同。這是個不錯的設計,如tk33中的「避免掩蓋繼承而來的名稱」,同時也避免了「重新定義乙個繼承而來的非虛函式」。但對於嚴格的編譯器而言,上述**無法通過編譯(vc可以通過,g++不能)、、、、因為編譯器看不到sendclear函式的存在。

問題在於:模版類logmsgsend定義時,並不知道它繼承了什麼樣的類,雖然是msgsend,但不到例項化時無法知道具體是什麼、如果不知道company是什麼,也就無法知道msgsend是什麼。。。說到底就是,這種情況下無法知道它是否有sendclear函式。

我們例項來分析,假設有乙個companyz用於加密通訊

class companyz

;

一般性的msgsend模版對這種類並不合適,因為模板提供乙個sendclear函式。如果對其型別引數呼叫sendclear函式,對companyz物件並不合理。解決此問題的方法是提供針對companyz提供乙個msgsend特化版本:

template<>

class msgsend

};

「template<>」語法表示:這既不是標準類,也不是模版,而是個特化的msgsend模版,在模版實參是companyz時使用。這就是所謂的模板全特化:特化是全面的,即如果一旦引數特化為companyz,就再沒有其他模版引數可供變化。

現在全特化以後我們再次考慮派生類中的logsendclearmsg

templateclass logmsgsend : public msgsend

};

很顯然當基類指定為msgsend時這段**不合法。這也是c+拒絕這種呼叫的原因:基類模版可能被物化。因此拒絕在模版化基類中尋找繼承而來的名稱。

解決辦法1:

templateclass logmsgsend : public msgsend

};

方法2:使用using宣告式

templateclass logmsgsend : public msgsend

};

這裡情況和避免派生類掩蓋基類名稱不同,而是編譯器不進入基類作用域查詢,於是我們告訴它,讓它這麼做。

方法3

templateclass logmsgsend : public msgsend

};

但方法3並不是好的解法,因為如果被呼叫的是虛函式,那麼明確修飾會關閉「virtual」的繫結行為。

上面三方法做的事情都相同:對編譯器承諾「任何基類模版的特化版本」都支援其一般介面。

這個是編譯器在解析派生類模版時需要的。如果出現下面原始碼:

logmsgsendzmsgsender;

msginf msgdata;

zmsgsender.sendclear(msgdata); //錯誤,無法通過編譯

在這個點上,編譯器知道基個是個特化版本,且不提供sendclear函式。

根本而言:上面討論的都是面對「基類成員的無效引用」,編譯器的診斷可能發生於早期(解析派生類模版的定義式),也可能是晚期(模版被特定的模版引數例項化)。c++的原則是盡早診斷。這也說明了為什麼「基類從模版中被例項化時」,它假設它對那些基類內容毫無所知。

需要記住的:

可在派生類模版中通過「this->」涉及基類模版內成員名,或明白寫出「基類資格修飾符」

43 學習處理模版化基類內的名稱

1 考慮下面的場景,有個類模版templatebox 內部有個方法 現在子類templateclass bigbox public box bigbox內部使用方法 考慮出現什麼問題?2 首先一點,類模版產生出來的類之間,沒有關係。也就是box與box沒有關係。通過指定模版實參,可以產生不同的模板類...

條款43 學習處理模板化基類內的名稱

條款43 學習處理模板化基類內的名稱 know how to access names in templatized base classes.內容 現在我們接到乙個編碼任務,任務要求我們的目標程式能夠傳送資訊到不同的公司去.這裡的資訊可以分為 被譯成密碼的資訊和未經加工資訊明文資訊.我們分析了任務...

條款43 學習處理模板化基類的名稱

先看程式 class a templateclass drivedusea public usea int main 1.在基類函式呼叫動作之前加上this this useafunc 2.使用using宣告 templateclass drivedusea public usea 3.明確指出被調...