Item 43 訪問模板基類中的名稱

2022-05-28 04:33:10 字數 1852 閱讀 4380

從面相物件 c++ 轉移到模板 c++ 時,你會發現類繼承在某些場合不在好使了。 比如父類模板中的名稱對子類模板不是直接可見的,需要通過 this-> 字首、using 或顯式地特化模板父類來訪問父類中的名稱。

因為父類模板在例項化之前其中的名稱是否存在確實是不確定的,而 c++ 偏向於早期發現問題(early diagnose),所以它會假設自己對父類完全無知。

乙個 msgsender 需要給多個 company 傳送訊息,我們希望在編譯期進行型別約束,於是選擇了模板類來實現msgsender。

templateclass msgsender    // 傳送明文訊息

void sendsecret(const msginfo& info) // 傳送密文訊息

};

由於某種需求我們需要繼承 msgsender,比如需要在傳送前記錄日誌:

templateclass loggingmsgsender: public msgsender

};

首先要說明這裡我們建立了新的方法 sendclearmsg 而不是直接重寫 sendclear 是乙個好的設計, 避免了隱藏父類中的名稱;也避免了重寫父類的非虛函式。

編譯錯誤發生的原因是編譯器不知道父類msgsender中是否有乙個 sendclear,因為只有當company 確定後父類才可以例項化。 而在解析子類 loggingmsgsender 時父類 msgsender 還沒有例項化,於是這時根本不知道 sendclear 是否存在。

為了讓這個邏輯更加明顯,假設我們需要乙個公司companyz,由於該公司的業務只能傳送密文訊息。所以我們特化了 msgsender 模板類:

template<>

class msgsender // 沒有定義sendclear()

};

template<>意味著這不是乙個模板類的定義,是乙個模板類的全特化。 我們叫它全特化是因為 msgsender 沒有其它模板引數,只要 companyz 確定了 msgsender 就可以被例項化了。

現在前面的編譯錯誤就更加明顯了:如果 msgsender 的模板引數 company == companyz, 那麼 sendclear() 方法是不存在的。這裡我們看到在模板 c++ 中繼承是不起作用的。

既然模板父類中的名稱在子類中不是直接可見的,我們來看如何訪問這些名稱。這裡介紹三種辦法:

父類方法的呼叫語句前加this->

templateclass loggingmsgsender: public msgsender

};

這樣編譯器會假設 sendclear 是繼承來的。

把父類中的名稱使用 using 宣告在子類中。

templateclass loggingmsgsender: public msgsender

};

using 語句告訴編譯器這個名稱來自於父類msgsender

最後乙個辦法是在呼叫時顯式指定該函式所在的作用域(父類):

templateclass loggingmsgsender: public msgsender

};

這個做法不是很好,因為顯式地指定函式所在的作用域會禁用虛函式特性。萬一 sendclear 是個虛函式呢?

子類模板無法訪問父類模板中的名稱是因為編譯器不會搜尋父類作用域,上述三個辦法都是顯式地讓編譯器去搜尋父類作用域。 但如果父類中真的沒有 sendclear 函式(比如模板引數是companyz),在後續的編譯中還是會丟擲編譯錯誤。

條款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.內容 現在我們接到乙個編碼任務,任務要求我們的目標程式能夠傳送資訊到不同的公司去.這裡的資訊可以分為 被譯成密碼的資訊和未經加工資訊明文資訊.我們分析了任務...

C 基類成員在派生類中的訪問屬性 總結

首先回顧一下三種成員訪問限定符 public 公用的 既可以被本類中的成員函式所引用,也可以被類的作用域內的其他函式 即類外 引用。private 私有的 只能被本類中的成員函式引用,類外不能呼叫 友元類除外 protected 受保護的 不能被類外訪問,但可以在派生類的成員函式訪問。接下來就用一張...