看板 C_and_CPP 關於我們 聯絡資訊
(1)菱形繼承 導致了二義性問題,有幾種方式解決 一種是限制繼承深度,讓菱形繼承無法出現 一種是使用虛擬繼承,但虛擬繼承本身帶來以下問題(細節見Effective C++ Item 40) 虛基類初始順序較複雜 由最終派生類呼叫虛基類ctor,容易踩坑 佔比較多的空間,且影響data存取速度 (2)指標偏移 父類指標與子類指標指向同一實體,但位址未必相同 不過指標拿來做比較運算時相同,因為會隱式轉型成父類指標再比較 (3)轉型導致虛函數執行結果無法預期 第一種情況是涉及void*,導致轉型時指標不偏移 第二種情況是使用不偏移指標的轉型:reinterpret_cast (4)More Effecitve C++ Item M24 影響效能且佔比較多的空間 (5)Google C++ Style Guide 多重繼承本身帶來的效能影響比虛擬繼承還高 避免多重實作繼承 (6)Effective C++ Item 40 public介面繼承 + private實作繼承 (7)C++ Core Guidelines C.135 用多重繼承表示多個不同的介面,這些介面通常是抽象類 (8)C++ Core Guidelines C.136 用多重繼承表示實現特性的合併;此item認為優先使用單一繼承 (9)Modern C++ Design 第一章的policy based design,結合多重繼承跟template 第三章的hierarchy generator,現在可以用variadic template簡化 (10)C++ Templates: The Complete Guide 21.3 mixin,能在不複製介面的情況下增加data成員或其他操作 為了增加任意數量的base,會用到variadic template 補充: mixin跟policy based design都是多重實現繼承 前者與派生類有"-ABLE"的關係 後者強調在相同介面下選擇何種行為,而不是增加data成員或其他操作 前者應採用public繼承,後者應採用private繼承 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 125.227.113.163 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1624423252.A.26D.html
KanzakiHAria: 少用繼承多用組合 06/25 12:26
loveflames: 優先用組合是當然,不過講這個又要提bridge pattern了 06/25 12:28
loveflames: C++官網也有探討過這個 06/25 12:28
ShenJing: 感謝整理 06/25 15:03
既然推文提到優先使用組合,那麼就進一步討論這個 基本上就是因為繼承的耦合度比較高 除了編譯相依性外,修改父類很可能導致子類一起修改,我想了幾個可能情境 父類原本沒有與子類同名的函數,後來加上去 父類允許的繼承深度遭到改變 父類從一般繼承改成虛擬繼承祖父類 父類有無不變式(invariant)的性質遭到改變 (不知道不變式是什麼的,請參考Google C++ Style Guide跟C++ Core Guidelines) 另外,C++官網列了三個經驗法則 https://isocpp.org/wiki/faq/multiple-inheritance 經驗法則1:僅當這樣做會刪除if/switch語句時使用繼承 經驗法則2:多重繼承盡量繼承抽象類 經驗法則3:考慮bridge pattern跟nested generalization能否作為替代方案 如果採用以上連結內容的觀點 以二維(M種產品 + N種顏色)為例,考量三種方案的優缺點 多重繼承 優點:可同時為產品維度跟顏色維度提供多型 缺點:多重繼承跟虛擬繼承帶來的問題 可能是優點也可能是缺點:有M x N個實作類別 bridge pattern 優點:將顏色維度分離出去,繼承關係變成組合關係 缺點:無法在編譯期排除某些組合(例如:背包 + 黑色) 可能是優點也可能是缺點:有M + N個實作類別 nested generalization: 缺點:第一層產品維度 + 第二層顏色維度,無法共享顏色維度的代碼 可能是優點也可能是缺點:有M x N個實作類別 ※ 編輯: loveflames (125.227.113.163 臺灣), 06/25/2021 16:21:34
KanzakiHAria: 推推 06/25 21:00
DerLuna: 不要用繼承 06/27 19:01