C++中抽象類別和介面類的區別

來源:互聯網
上載者:User

    文章出處:http://blog.sina.com.cn/s/blog_49652a2d0100fk3n.html

 

    Bill Venners:

    我在1991至1996這5年間,幾乎一直僅僅使用C++編程。在那時,我認為多重繼承的唯一目的就是讓我能夠從多個基類中繼承它們各自的資料和函數——不管是虛擬函數還是非虛擬函數。那時候, 我和我使用C++的同事幾乎從未想過可以使用一種不含任何資料而僅包含虛函數的類,也就是現在Java中被稱為介面的東西。最近您好像又越來越多的提起了抽象類別這個概念,我想問問是不是最近在實驗的過程中發現了一些我們以前未曾注意到的對純介面類進行多重繼承的好處,抑或是您認為我們以前對抽象類別重視的不夠?

    Bjarne Stroustrup:

    我在對人們解釋這個問題的過程中遇到了很多問題,而且我也一直不能理解為什麼讓人們理解這個問題是如此困難。自C++出現那天起,就存在著包含資料成員的類和不包含資料成員的類。在過去,人們強調利用一個最基礎的設施以及該設施內部的東西來構造軟體系統,而那個“最基本的設施”通常就是抽象基類。從80年代中葉到80年代末,那些僅由虛擬函數組合而成的類通常都被稱為ABCs(Abstract Base Class 抽象基類)。1987年,我在C++中加入了純虛函數的概念,一個純虛函數必須被其衍生類別重寫。藉助此概念,你可以在一個C++類中通過將其成員函式宣告為純虛函數的方法表明該類是一個純介面類。從那以後,我就一直強調,在C++中,有一種主要的使用類的方法就是讓該類不包含任何狀態,而僅僅作為一個介面

    從C++的角度來看,一個抽象類別和一個介面之間沒有任何區別。有時,我們習慣使用“純抽象類別”這個詞來表示某個類僅僅只含有純虛函數(不包含任何資料成員),它是抽象類別的最常見的形式。當我試圖向人們解釋這個概念時,我發現如果我不先向它們介紹純虛函數這個語言中被直接支援的概念,人們就很難接受它。有些人僅僅因為可以在基類中放入一些資料成員,就覺得他們必須這樣做。他們這樣做,就等於構造了經典的不穩定基類,當然同時也就招致該結構所帶來的一切問題。當我向人們介紹C++中直接支援抽象基類的概念時,情況稍微好一些,不過仍然有許多人不能理解它。我認為這是由於我自身的原因所造成的教育上的失敗——我低估了做這件事的難度。這與早些時候Simula社團在理解新概念上的失敗異常相似。有些新概念難以理解,部分原因在於許多人並不是真的想去學習一些全新的東西,他們自以為自己已經知道了答案。而一旦以為自己已經知道了答案,再去學一些新東西就會變得非常困難。在1991年的《The C++ Programming Language》第二版中,有幾個例子描述了抽象類別的概念,可不幸的是,我並沒有在全書從頭至尾都貫穿這個思想。

    Bill Venners:

    使用純抽象類別有什麼好處?什麼時候我們應該使用純抽象類別而不是使用更為普遍的多重繼承?

    Bjarne Stroustrup:

    最明顯的例子就是“多介面,單實現”,這是一種很常見的情況。例如,你的系統也許既需要序列化功能,也需要迭代功能,那麼這兩個功能都可以介面的形式利用抽象類別提供。然後,如果需要提供一個支援序列化的容器,你只需要讓容器類繼承序列化抽象類別和迭代抽象類別就可以了,而這種多重繼承的形式已被Java和C#採納。

    另一種通常需要使用多重繼承的情況是僅僅通過多重繼承將手頭的一些類組合起來。它們每一個都沒有特別複雜的語義,將其組合起來完全是出於使用上的方便。當然,你也可以使用委託的模式來完成這個工作,也就是說,你可以在對象中容納一個指向真正實現某些功能的對象指標。這種方法雖然也不錯,但每當你在間接對象中添加一個新方法時,你都需要在自己的類中對應地增加一個新方法。這種做法真讓人頭痛,而且也沒有直截了當地表示出原本的想法,維護起來則更是費時費力。最後一種情況是你需要從兩個類中分別繼承它們各自的狀態。在這種情況下,當這兩個類都非常複雜或它們的語義相互影響時,你很容易陷入混亂之中。然而你可以通過減少過度繼承的方法盡量減少這種情況發生的次數,而當你不可避免地需要使用繼承時,你可以通過盡量減少過度使用多重繼承達到目的,而如果到了連多重繼承都是非要不可的時候,那麼你應該盡量迴避那些複雜的變數。總的來說,在對一個具體問題建立一個模型時,你應該讓該模型盡量簡單,但不致於過分簡單。

    有些人經常會說他並不需要多重繼承,因為所有多重繼承能做的事情都能通過單繼承完成,只是要使用我上面提到的那個名為“委託”的小技巧而已。更進一步,你也並不需要任何繼承,因為所有單繼承能夠完成的事都可以通過類之間的轉寄完成。實際上,你根本不需要任何類,因為你完全可以利用指標和資料結構來達到目的。可為什麼你會想要建立類呢?什麼時候使用語言內建設施比較方便?什麼時候你寧願用一種繞彎的方法呢?我見過有很多場合多重繼承甚至是非常複雜的多重繼承發揮了重要作用。總體上來說,我更喜歡使用語言提供的功能來處理事情。

    我們應對複雜情形的另外一種方法是利用模板進行組合。具體而言就是提供多個模板參數,而每個參數都是一個完全獨立的類,它們都是你能夠進行組合的抽象的具體實現。這些類每一個都是完全獨立的,只有最後的衍生類別才與它們中的每一個存在依賴關係。有時候在一個模板內部根據繼承關係進行組合是很便捷的,而有時則需另想辦法(例如你可以將每一個單獨的類作為一個資料成員儲存或僅儲存它們各自的指標)。這裡有一個你有時需要從多個類中繼承狀態的例子:你有一個配置器對象,它知道如何處理關於記憶體的分配和銷毀的問題,你也有一個存取器對象,只要你把記憶體位址給它,它就能處理關於記憶體存取的問題。現在,你準備將他們都用於你的一個項目實現中,就讓我們假設是一個操作矩陣的複雜函數吧,此時你至少已經擁有了兩個狀態量,可是並沒有帶來那些對多重繼承心存疑慮的人所擔心的那些問題。基本上,你用一些非常簡單的詞彙就可以將運作的情況解釋清楚。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.