前言【【C語言基礎(chǔ)】C ++中廣泛使用的技術(shù)之模板元編程,讓繼承作為一種技術(shù)工具】https://toutiao.com/group/6586910869827895815/?iid=15906422033&app=explore_article×tamp=1533652528&group_id=6586910869827895815&tt_from=copy_link&utm_source=copy_link&utm_medium=toutiao_ios&utm_campaign=client_share 更多C/C 學(xué)習(xí)資料,請私信我“代碼”,即可獲取 C 是一種多范式語言,因此它不是純粹的面向?qū)ο笳Z言,而是具有其他方面,例如通過模板對通用編程的巨大支持。其主要優(yōu)勢之一是能夠混合這些不同方面。 繼承是C 中主要面向?qū)ο蟮姆矫嬷?,在純粹的面向?qū)ο蟮纳舷挛闹校馕吨癐s-A”關(guān)系。在與C 的其他方面的混合中,繼承可以用于純粹的技術(shù)和其他原因,這些原因并不意味著面向?qū)ο蟮淖宇愋汀?/p> 在本文中,我將探討在C 中繼承的可能用途。 更多C/C 學(xué)習(xí)資料,請私信我“代碼”,即可獲取 面向?qū)ο?/strong>我將假設(shè)以面向?qū)ο蟮姆绞绞褂美^承是充分已知的,因此我不會詳細(xì)介紹Liskov替換原則和該主題的其他一般方面。但是有一些方面與C#或Java等其他語言不同,所以我將在這里簡要介紹一下。 構(gòu)造函數(shù)和析構(gòu)函數(shù)中的虛函數(shù)更多C/C 學(xué)習(xí)資料,請私信我“代碼”,即可獲取 我假設(shè)您了解虛擬功能以及它們的工作原理。然而,對于許多C 開發(fā)人員而言,在構(gòu)造函數(shù)和析構(gòu)函數(shù)中使用虛函數(shù)令人驚訝。請考慮以下代碼: 更多C/C 學(xué)習(xí)資料,請私信我“代碼”,即可獲取 許多人會期望打印字符串“Derived :: foo”,因為它是一個“Derived”對象,它被創(chuàng)建。但是如果你知道編譯器在構(gòu)造對象時做了什么,很明顯為什么不會發(fā)生這種情況: 構(gòu)造`Derived`對象時,首先要構(gòu)造該對象的`Base`部分。`Derived`對象尚未開始存在。作為“派生”對象的整個事物的身份在其所有部分(包括“Base”子對象已經(jīng)初始化)之后得到建立。因此當(dāng)調(diào)用`foo()`時,除了一個`Base`對象之外什么都沒有,因此可以調(diào)用的唯一`foo`是`Base :: foo`。 同樣的推理適用于析構(gòu)函數(shù)中的虛函數(shù)調(diào)用:`Base`析構(gòu)函數(shù)在`Derived`對象的所有其他部分都被銷毀后作為最后一步執(zhí)行,然后作為`Derived`的對象的身份已經(jīng)結(jié)束。 虛擬析構(gòu)函數(shù)上面的`Base`類沒有正確編寫。根據(jù) Herb Sutter的這條規(guī)則,“Base”的析構(gòu)函數(shù)應(yīng)該是虛擬的或受保護(hù)的。虛擬,如果你想能夠在`Base`類指針上調(diào)用`delete`,包括使用`Base`智能指針,否則保護(hù)。 由于面向?qū)ο蟮睦^承通常與某種基類指針密切相關(guān),因此將析構(gòu)函數(shù)設(shè)置為public和virtual是正確的選擇。因此,考慮到 全部規(guī)則或無規(guī)則,“基礎(chǔ)”應(yīng)如下所示: 更多C/C 學(xué)習(xí)資料,請私信我“代碼”,即可獲取 這看起來像是一個巨大的開銷,但是在最頂層的基類中聲明虛擬析構(gòu)函數(shù)就足夠了,任何派生類的析構(gòu)函數(shù)也將自動虛擬化。 多重繼承除了允許類僅從單個其他類派生并且可能實現(xiàn)一個或多個接口的許多其他語言之外,C 允許實際的多重繼承。這意味著,允許一個類派生自多個完全成長的類,每個類都有自己的成員變量,虛擬和非虛函數(shù)等等。 這可能會導(dǎo)致一些問題,其中一些問題非常微妙且違反直覺。例如,如果兩個基類具有相同名稱的函數(shù),則在派生類中調(diào)用其中一個可能不明確。如果兩個基類派生自同一個類,則形成“致命的死亡之鉆”,這就是C 具有虛擬繼承的原因。 繼承作為一種技術(shù)工具更多C/C 學(xué)習(xí)資料,請私信我“代碼”,即可獲取 當(dāng)一個類派生自另一個類時,它不僅繼承了成員變量和方法,還繼承了該類的任何typedef和靜態(tài)成員。這可以在不同的場合使用。 模板元編程C 中廣泛使用的技術(shù),特別是庫編寫者,是模板元編程。它通常涉及只包含typedef和常量定義的小類。通常這些類永遠(yuǎn)不會被實例化,即沒有創(chuàng)建它們的對象。 模板元編程中使用的許多類相互派生,以利用其基類中的常量和typedef的繼承,而不必重新定義它們。這類的示例是模板` std :: integral_constant`。它的兩個實例化,`std :: true_type`和`std :: false_type`它包含兩個typedef和一個靜態(tài)常量值,在這種情況下分別是`true`和`false`。 模板元函數(shù)的一個非常簡短的示例是一個小模板,用于確定unsigned int是偶數(shù)還是奇數(shù): 更多C/C 學(xué)習(xí)資料,請私信我“代碼”,即可獲取 從通用實施細(xì)節(jié)中獲取有時,有幾個類共享其實現(xiàn)的一些常見細(xì)節(jié)。將實現(xiàn)分解為所有這些類使用的另一個類是正常的。通常的選擇是使實用程序類的對象成為每個類的私有成員,但是實現(xiàn)者可能會選擇從實用程序類派生而來:
奇怪的重復(fù)模板模式所述CRTP是模板和繼承在C 一起工作的另一個例子。這意味著一個類派生自一個僅使用派生類實例化的模板: 更多C/C 學(xué)習(xí)資料,請私信我“代碼”,即可獲取 使用此技巧的最常見場合之一是靜態(tài)多態(tài):基類可以調(diào)用派生類的方法,而無需為它們定義虛擬原型。這些方法的調(diào)用可以比虛函數(shù)調(diào)用快一點。但是,兩個派生類沒有公共基類,因為它們派生自模板的兩個不同實例,它們是不同的類。 結(jié)論在C 中有許多可以使用繼承的方法,其中許多方法并不意味著面向?qū)ο蟮摹癐s-A”關(guān)系。通??梢酝ㄟ^最頂層基類中的公共虛擬析構(gòu)函數(shù)來識別那些。 |
|
|