這歷來是一個受爭議的話題,書上的樣板話我就不說了。我只說說自己的一點觀察和體會:
1. 多重繼承在理論上是有道理,21天學通C++里舉了一個例子,就是飛馬繼承於飛鳥(會飛)和馬(會跑),你可以定義一個函數func1,使之有時候飛有時候跑(5公里以內跑,更遠就飛),看上去兩全其美,但如果既要飛又要跑呢?這樣的自定義函數就解決不了問題了。非得多繼承才行。總結:多繼承理論上是有道理的。
2. 現實生活中,完全多繼承的情況很少。比如人雖然繼承自父母,但也只是繼承了一部分功能,還得加上自己的某些基因突變,所有會有自己的脾氣和其它特性,相反使用組合的情況非常多。總結:多繼承的情況很少,也不實用。
3. 接口分擔了多繼承的大部分功能,使得多繼承更加顯得不那么必要。當然,接口沒有實現相關的功能。如果想要直接使用別人已經實現的功能,仍然無法完成這個任務。但是可以在內部使用組合對象,使用一句話實現相關函數,就可以偽裝成實現接口功能。總結:接口分擔了相當一部分功能,估計這也是C++始終沒有加入接口的原因,因為不需要嘛,有多繼承和純虛函數就已經達到了同樣的目的,雖然不夠優雅。另外要提一句的是,接口看上去更優雅。如果編譯器支持的話(比如Delphi),可以自動釋放內存,還可相互探測和轉化,十分方便和強大。
4. 多繼承雖然有道理,但是與生俱來帶來了一些使用上的麻煩:菱形內存接口是很痛苦的,什么虛繼承之類的煩不勝煩,我還有個疑惑是,誰能提前想到自己正在定義的類將來是要被虛繼承的啊?如果沒想到就不會提前加上關鍵字,就達不成虛繼承的目的。讓別人提起知道某些事情,就破壞了OO的好處。另外菱形布局對虛函數表也有影響,好像有多個虛函數表,這在侯捷翻譯的《深入C++探索》一書有詳細描述,我也只是看了一眼,以后再補充。總結:使用太麻煩,內部實現也相當復雜,虛繼承似乎破壞了OO的純潔性。
5. 今天在論壇上看到一個問題:“如何監控一個對象是否被析構”,回答多種多樣:比如析構的時候發一個信號;如果不是實時需要,自己探測對象指針是否為NULL。但是有一個回復引起了我的注意:讓所有子類都繼承你的類,在那個類在析構的時候監控一下就好了。這句話立刻讓我想到了C++多重繼承的強大功能,這是我之前從未想到過的,而且這個功能強大到可以被濫用。
即:我讓項目中所有的類全部繼承我自己定義的某個類,也不會影響原來的類繼承正常的別的類。這樣就有利於項目的全局管理和控制,或者快速的給所有類加上某項強大功能。對於那些不支持多繼承的語言就不行了(現實中好像只有C++支持多繼承,不知道有沒有別的語言也支持,歡迎補充),只能通過組合來實現,那樣就要修改每一個類的內部實現,哪怕僅僅是在每個類里增加一句話也是夠麻煩的,而且同樣破壞了OO的純潔性。這個功能很值得深思,而且不僅僅可以改寫項目里的類,有空或許可以試試改寫類庫(比如MFC)里的類,使類庫也被置於程序員的強大控制之下,這樣一個強大的類,其作用甚至遠遠超過CObject和QObject。
總結:C++多繼承很強大,強大到在不影響正常功能的情況下可以控制一切,強大到可以被濫用,有空一定要試試給全部類繼承自己的類,看看能不能達到某種以前沒有達到過的境界。
6. C++雖然沒有接口,但卻有純虛類,這樣就在一定程度上替代了接口的作用。如果使用純虛類的指針,再加上多繼承的強大功能,雖然不如純接口那么優雅,但是也已經非常實用了。
7. 在理論上有一個把許多人繞暈的“虛繼承”問題,其實在現實生活中幾乎不存在,所以不必在意。看看在現代化重新設計的QT類庫就知道了,大量用到了多繼承,比如QWidget就是,不但沒有思維上的干擾,反而非常實用和強大。如果出現要處理虛繼承的情況,只能說這個類庫的設計已經差到了極點。
----------------------------------------------------------------------------
我在求學的時候了解過一些開源庫,比如說OggVorbis、7-zip以及github上的一些開源庫,還有微軟的DirectX庫,COM組件等
其中了解了一些編程模式,
懂得了使用C++的一些特殊語法可以達到很多意想不到的效果,即使是C++98。
比如說剛剛那個就是COM的編程思想。
有道理,都是實用派的編程模式吧。
像什么《設計模式》這樣的經典書里是不會講到這個的。