[Happy Coding] 只能new不能delete的基类实现方法

1. 问题提出
定义一个类,客户端只能new不能delete,但是要求这个类能够被继承。


2. 问题分析
客户端代码能够new一个类实例,说明这个类提供了对应的public访问域的构造函数,不能delete它,说明这个类没有提供public访问域的析构函数。也就是说,析构函数要么是在protected访问域中,要么是在private访问域中。但是要求这个类能够被继承,至少说明析构函数得是virtual的。如果析构函数是在private访问域中,那么被继承的子类肯定无法析构成功(无法编译),因为private成员无法在子类中可见。所以这个类的析构函数只能定义在protected访问域中。
但是定义在protected访问域中,客户端无法delete,那就会造成内存泄漏,因为它只能new在堆上,而且也无法构造在栈上。

3. 问题解决
那么我们只能让这个类提供一个interface,叫做release,客户端代码手动调用。其实这个情况,在wxWidget代码很常见,就是所有的窗口子类实例化时都是new在堆上,窗口退出时,并不调用delete,而是窗口遍历调用各个子窗口的Destroy函数,来清除所有的资源。这个Destory函数干的事情也很简单,就是delete this。
下面就是一个简单的实现案例,这个类是一个引用计数类:
class RefCountedObject {
public:
    RefCountedObject()
    : count(1)
    { std::cout << "RefCountedObject::RefCountedObject:()\n"; }


    void duplicate() {
        ++count;
    }
    void release() {
        if (--count == 0)
        {
            delete this;
        }
    }
protected:
    virtual ~RefCountedObject() {
        std::cout << "delete RefCountedObject\n";
    }


private:
    RefCountedObject(const RefCountedObject&);
    RefCountedObject& operator=(const RefCountedObject&);
    int count;
};




class A : public RefCountedObject
{
protected:
    ~A() {
        std::cout << "delete A\n";
    }
};


int main()
{
    A* pa = new A();
    //A aa;  // cannot compile, since its dtor is protected
    //delete pa; // can not compile, too 
    pa->release();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值