设为首页 加入收藏

TOP

C++实现对象和接口的弱引用(一)
2013-05-03 18:17:55 来源: 作者: 【 】 浏览:149
Tags:实现 对象 接口 引用
  弱引用是相对于强引用而言,它引用一个对象但是又不控制对象的生存时期,然后在使用时需要先检查引用的对象是否还存在。而强引用,一般是基于引用计数,引用计数明确的控制了对象的生存时期。如果按控制关系排一个顺序,就是:强引用控制对象生存时期,对象生存时期控制弱引用是否有效,弱引用则什么也没控制,它本身就是一个对象(例如C#里的System.WeakReference),高级一点可以是个模板。
 
  弱引用貌似是各种高级语言中的神器,不过只要想费一点功夫,C++(www.cppentry.com)语言也可以实现,本文实现的版本是一个模板。弱引用实现的关键在于,当对象被删除时,需要及时的改变弱引用的状态,这需要引用的对象本身实现这些功能。因此为了实现弱引用,必须规定一个支持弱引用的基类,然后继承它的类都可以支持弱引用。这个类设计出来大概是这个样子:
 
  h文件代码
 
  [cpp] view plaincopy
  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_ref 和 release_weak_ref 实现,add_weak_ref 是用来记下一个WeakRefObj* 变量的地址,通过记录变量地址 WeakRefObj**,这个变量就变成形式上的弱引用了。release_weak_ref 是把一个WeakRefObj* 变量的地址从记录中删除,使它还原为普通的变量。还有一个关键的函数,析构函数,其中要对已经记录的变量进行清零,这样当对象被删除后,所有被当做弱引用的变量都变成空值。在高级语言中,这个操作可能是垃圾回收器在某个时刻延时完成的,但在C++(www.cppentry.com)里必须在析构时全部清零。这样,弱引用的所有功能就算实现了。
 
  不用多说,这里面有一大堆多线程同步问题要解决,不过先不考虑这些,暂时允许代码不是线程安全的。下面的实现过程中,记录的变量地址需要由 WeakRefObj 本身来保存,最简单的就是用std::set<T> 容器,void* _internal 可以指向一个std::set<WeakRefObj**>。
 
cpp文件代码
 
[cpp] view plaincopy
#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_ptr)  
{  
    std::set<WeakRefObj**>* weak_refs = (std::set<WeakRefObj**>*)this->_internal;  
    weak_refs->erase(ref_ptr);  
    if(clear_ref_ptr)  
    {  
        (*ref_ptr) = NULL;  
    }  
}

       

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇不使用sizeof, 计算int的位.. 下一篇C++中点操作符和箭头操作符

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: