Abstract
C++中一旦用到pointer,就得自己管理memory,若功力不夠,不是當機就是memory leak,所以能避免就避免,不過若要在container中放polymorphism object,就只能使用pointer,此時該如何big three呢?
Introduction
在(原創) 若class中的data member有container,而且內含pointer時,也一定要big three!!(C++) 中已經討論了container中放pointer中該如何處理,但別忘了我們為什麼會在container中放pointer呢?就是為了polymorphism,所以一定會遇到一個inheritance hierarchy,而非之前討論的只有一層class。
我們知道處理big three中,主要就是要在copy constructor和assignment operator中重新new過,而非只是copy pointer,但因為container中放的是polymorphism object,我該怎麼針對適當的type去new呢?
我的第一個想法,就是用RTTI去判斷該polymorphism object的type為何,然後去new。
2
3
4
5
6
7
8
執行結果
執行結果如預期,但copy contructor和assignment operator非常的醜
由於使用了RTTI,須不斷的去判斷type,這種寫法明顯的違反了OCP,若有新的type,就得改copy constructor和assignment operator的判斷式,算是很差的寫法。
再苦思許久之後,大陸的袁老弟給我一個建議,使用clone(),在Modern C++ Design 8.7節有個範例就是用這種方式,我試了之後,結果非常令我滿意。
Sample Code
執行結果
37行
在base class多定義了clone member function,專門負責做clone。
50行
重點來了,derived class override了clone(),但return type變成Derived1*,而不是Base*,這和我們一般polymorphism寫法不一樣,Modern C++ Design 8.7節稱此為covariant return type,讓你override virtual時,可以不使用Base *,利用這個特色,我們就能clone出完整的object。
79行
copy constructor就變的非常的簡單,而且mem_fun(&Base::clone)還支援polymorphism,相當漂亮,程式只要一行就解決,而且符合OCP,若未來有增加type,也不用再修改程式。
Conclusion
Modern C++ Design 8.7節指出這種使用clone的方式有兩個缺點:
1.必須在base class增加virtual clone(),若使用的是component而無法修改程式時,將無法使用這種方法。
2.每個derived class一定要去override base class的virtual clone(),若忘記override clone(),程式結果將有錯誤,而且compiler也不會提醒你。
Modern C++ Design因此提出了Clone Factory Pattern來解決這個問題,不過我還沒看懂這個pattern,但目前看起來使用clone()的方式還算不錯。
See Also
(原創) 若class中的data member有container,而且內含pointer時,也一定要big three!!(C/C++)
Reference
Andrei Alexandrescu,Modern C++ Design,Addison Weseley,2001