作者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
1F:推 minazukimaya:静态多型也是多型啊..主要的问题在於有没有动态绑定 10/08 09:35
2F:→ minazukimaya:的需求吧.. 10/08 09:35
3F:→ minazukimaya:动态多型最重要的好处是可以用一个container就处理 10/08 09:35
4F:→ minazukimaya:heterogeneous collection.. 10/08 09:35
5F:推 minazukimaya:C++ templates: the complete guide第14.3节有讨论这 10/08 09:40
6F:→ minazukimaya:两者分别适用在哪些地方 10/08 09:40
7F:→ cplusplus:sure @@ 我最後指的是deliver一个bin library之类的情况 10/08 10:42
8F:→ cplusplus:好几篇之前我也有回别人静态多型是利用甚麽... 10/08 10:43
9F:→ legnaleurc:sorry, 我就是这麽贴心 orz 10/08 12:20