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。

  1(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)#include <iostream>
  2(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)#include <vector>
  3(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)#include <algorithm>
  4(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)#include <functional>
  5(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)
  6(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)using namespace std;
  7(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)
  8}


執行結果

(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)Base's print:1
(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)Derived1's print:
2
(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)Derived2's print:
3
(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)Base's print:
1
(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)Derived1's print:
2
(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)Derived2's print:
3


執行結果如預期,但copy contructor和assignment operator非常的醜


由於使用了RTTI,須不斷的去判斷type,這種寫法明顯的違反了OCP,若有新的type,就得改copy constructor和assignment operator的判斷式,算是很差的寫法。

再苦思許久之後,大陸的袁老弟給我一個建議,使用clone(),在Modern C++ Design 8.7節有個範例就是用這種方式,我試了之後,結果非常令我滿意。

Sample Code

  1}


執行結果

(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)Base's print:1
(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)Derived1's print:
2
(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)Derived2's print:
3
(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)Base's print:
1
(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)Derived1's print:
2
(原創) 若class中data member的container,含的是polymorphism的pointer,該如何big three? (C/C++)Derived2's print:
3


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

相关文章:

  • 2021-12-01
  • 2021-11-08
  • 2021-08-26
  • 2021-05-15
  • 2021-12-03
  • 2021-10-23
  • 2021-05-16
  • 2021-05-24
猜你喜欢
  • 2022-01-14
  • 2021-12-03
  • 2021-06-19
  • 2022-01-27
  • 2021-12-26
  • 2022-01-10
  • 2021-12-31
相关资源
相似解决方案