Re: [問題] 多型的自動回收
看板C_and_CPP (C/C++)作者cplusplus (沒事多聊天~ 歡迎打屁)時間16年前 (2009/10/08 04:44)推噓2(2推 0噓 7→)留言9則, 3人參與討論串11/13 (看更多)
※ 引述《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
推
10/08 09:35, , 1F
10/08 09:35, 1F
→
10/08 09:35, , 2F
10/08 09:35, 2F
→
10/08 09:35, , 3F
10/08 09:35, 3F
→
10/08 09:35, , 4F
10/08 09:35, 4F
推
10/08 09:40, , 5F
10/08 09:40, 5F
→
10/08 09:40, , 6F
10/08 09:40, 6F
→
10/08 10:42, , 7F
10/08 10:42, 7F
→
10/08 10:43, , 8F
10/08 10:43, 8F
→
10/08 12:20, , 9F
10/08 12:20, 9F
討論串 (同標題文章)
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章