C++实现对象和接口的弱引用

  弱引用是相对于强引用而言,它引用一个对象但是又不控制对象的生存时期,然后在使用时需要先检查引用的对象是否还存在。而强引用,一般是基于引用计数,引用计数明确的控制了对象的生存时期。如果按控制关系排一个顺序,就是:强引用控制对象生存时期,对象生存时期控制弱引用是否有效,弱引用则什么也没控制,它本身就是一个对象(例如C#里的System.WeakReference),高级一点可以是个模板。

  弱引用貌似是各种高级语言中的神器,不过只要想费一点功夫,C++语言也可以实现,本文实现的版本是一个模板。弱引用实现的关键在于,当对象被删除时,需要及时的改变弱引用的状态,这需要引用的对象本身实现这些功能。因此为了实现弱引用,必须规定一个支持弱引用的基类,然后继承它的类都可以支持弱引用。这个类设计出来大概是这个样子:

h文件代码

struct WeakRefObj
{
private:
    void* _internal;
protected:
    WeakRefObj();
public:
    ~WeakRefObj();
    void add_weak_ref(WeakRefObj** ref_ptr);
    void release_weak_ref(WeakRefObj** ref_ptr, const bool clear_ref_ptr = false);
};

  既然是基类,总是希望尽可能的简洁,尤其希望极少甚至没有成员变量声明在头文件里。不过研究了很久,总是不能避免添加成员变量,为了不让头文件暴漏太多内容,只声明了一个void* _internal,实际内容在实现代码中才能取得。

  弱引用的关键功能通过 add_weak_refrelease_weak_ref 实现,add_weak_ref 是用来记下一个WeakRefObj* 变量的地址,通过记录变量地址 WeakRefObj**,这个变量就变成形式上的弱引用了。release_weak_ref 是把一个WeakRefObj* 变量的地址从记录中删除,使它还原为普通的变量。还有一个关键的函数,析构函数,在析构函数里要对已经记录的变量进行清零,这样当对象被删除后,所有被当做弱引用的变量都变成空值。在高级语言中,这个操作可能是垃圾回收器在某个时刻延时完成的,但在C++里必须在析构时全部清零。这样,弱引用的所有功能就算实现了。

  不用多说,这里面有一大堆多线程同步问题要解决,不过先不考虑这些,暂时允许代码不是线程安全的。下面的实现过程中,记录的变量地址需要由 WeakRefObj 本身来保存,最简单的就是用std::set<T> 容器,void* _internal 可以指向一个std::set<WeakRefObj**>

cpp文件代码

#include"WeakRefObj.h"
#include<set>
WeakRefObj::WeakRefObj
{
    this->_internal = new std::set<WeakRefObj**>();
}
WeakRefObj::~WeakRefObj
{
    if(this->_internal != NULL)
    {
        std::set<WeakRefObj**>* weak_refs = (std::set<WeakRefObj**>*)this->_internal;
        for(std::set<WeakRefObj**>::iterator i = weak_refs->begin(), i_end = weak_refs->end(); i != i_end; i++)
        {
            (*(*i)) = NULL;
        }
        delete weak_refs;
    }
}
void WeakRefObj::add_weak_ref(WeakRefObj** ref_ptr)
{
    std::set<WeakRefObj**>* weak_refs;
    if((*ref_ptr) != NULL)
    {
        weak_refs = (std::set<WeakRefObj**>*)(*ref_ptr)->_internal;
        weak_refs->erase(ref_ptr);
    }
    weak_refs = (std::set<WeakRefObj**>*)this->_internal;
    weak_refs->insert(ref_ptr);
    (*ref_ptr) = this;
}
void WeakRefObj::release_weak_ref(WeakRefObj** ref_ptr, const bool clear_ref_p
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值