作者cplusplus (沒事多聊天~ 歡迎打屁)
看板C_and_CPP
標題Re: [問題] 多型的自動回收
時間Thu Oct 8 04:44:38 2009
※ 引述《minazukimaya (水無月真夜)》之銘言:
: ※ 引述《yoco315 (眠月)》之銘言:
: : 不要 = ="
: : 既然資源是在 D 配的,D 要自己處理,不要給 B 管
: : 所以這邊改成這樣
: : virtual ~Base() {} // 蝦米都不做
: : 然後 D 加上解構子
: : virtual ~Derived () { // 我自己來 XD
: : D::doClose(); // ~B() 不能呼叫虛擬函數
: : } // 我自己呼叫應該沒問題吧???
: : 還是我哪邊錯惹??????????
: 如果我的理解沒錯
: 原po他希望的是 Derived裡面有個function負責relase資源
: 但是在錯誤使用(delete 前忘了呼叫close的時侯)能夠自動釋放
: 而且重要的是,希望能在Derived的設計者「忘了」在dtor呼叫doClose的時侯
: 只要是從Base class繼承出來的class都能自動的去呼叫doClose
我覺得這發生的機會比較少,如果會去改寫doClose的話,
應該不會忘了在dtor裡面加上自動呼叫。
我覺得原PO不是為了這個問題,而是原PO使用template method pattern,
想呼叫的是 close() 不是 doClose()。
// template method
close()
{
......
//some statements
doClose();
//some statements
SomeMoreVFunc();
//some statements
.....
}
如果真的"只是"要確保doClose()呼叫動作被叫到,那直接在dtor內呼叫 doClose() 的
特定實作版本就好了吧? 而且也應該不用擔心重複呼叫的問題,doClose()內應該有機制
要避免這件事情,且各自class的doClose應該只負責釋放自己的額外產生的資源。
virtual ~Base(){ Base::doClose(); }
virtual ~Derived(){ Derived::doClose(); }
virtual ~Derived2(){ } //沒改寫實作就不用特別呼叫
: 後面這就是重點了 因為Base和Derived的設計者有可能是不同人
: 可能document沒寫清楚 又或者單純忘記了 總之因為種種原因
: 原po希望能在Base class裡就自動的有機制去處理這件事..
也許真的是這樣,但如果是這樣,我到覺得不必為了避免錯誤的使用方法
而改變class的設計。因為我覺得會去改寫/繼承這些與資源釋放相關class的使用者
都應該是進階使用者。只有單純使用class的使用者才比較初階。
不過也許原PO真的這麼貼心也說不定 XD
: 所以現在的問題是:唯一在物件銷毀時會自動執行的只有dtor
: 但是dtor中又不能呼叫virtual function
: 解決方法也就很直觀了..那就是寫成兩個class 也就是把介面和實作分開來就好了
: 就像#1Ap2yPNw提到的那樣 剛好有個design pattern叫作bridge..
: 這有兩種寫法 動態多型的寫法就像前述文章那樣
: class Base {
: BaseImpl* pImpl;
: public:
: void open() { pImpl->doOpen(); }
: void close() { pImpl->doClose(); }
: void someOperation() { pImpl->someOperation(); }
: ~Base() { content->doClose(); delete pImpl; }
: }
: class BaseImpl {
: friend Base;
: virtual void doOpen()= 0;
: virtual void doClose()= 0;
: void someOperation() {};
: }
: 如此這般 Base只提供一個操作的介面
: 實際的動作是委託給BaseImpl進行的
: 這樣Derived class只要繼承BaseImpl 自然就能成為一個Base的實作體
只是比較醜一點 XD
Base b(new DerivedImpl());
shared_ptr ptr(new Base(new DerivedImpl()));
: 靜態多型的寫法是像下面這樣
: template <typename T>
: class BaseInterface {
: T impl;
: public:
: void open() {
: impl._open();
: }
: void close() {
: impl._close();
: }
: void someOperation() {
: impl._someOperation();
: }
: ~BaseImpl() {
: impl._close();
: }
: }
: class DerviedImpl { //implematation here };
: typdef BaseInterface<DerivedImpl> Derived;
: 靜態多型的方法可以省掉virtual function的呼叫成本
: 當然缺點就是沒辦法在run-time改變型別
: 不過如果以原po的需求:管理資源open和close的class集來說
: 應該不會要用動態多型..所以後者是比較建議的方法
我覺得多型在這種情形也用得很多耶
例如常見的 stream 就有很多種,需要資源管理也需要多型處理 :P
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 122.124.96.179
推 minazukimaya:靜態多型也是多型啊..主要的問題在於有沒有動態綁定 10/08 09:35
→ minazukimaya:的需求吧.. 10/08 09:35
→ minazukimaya:動態多型最重要的好處是可以用一個container就處理 10/08 09:35
→ minazukimaya:heterogeneous collection.. 10/08 09:35
推 minazukimaya:C++ templates: the complete guide第14.3節有討論這 10/08 09:40
→ minazukimaya:兩者分別適用在哪些地方 10/08 09:40
→ cplusplus:sure @@ 我最後指的是deliver一個bin library之類的情況 10/08 10:42
→ cplusplus:好幾篇之前我也有回別人靜態多型是利用甚麼... 10/08 10:43
→ legnaleurc:sorry, 我就是這麼貼心 orz 10/08 12:20