设为首页 加入收藏

TOP

C++实现对象和接口的弱引用(二)
2013-05-03 18:17:55 来源: 作者: 【 】 浏览:151
Tags:实现 对象 接口 引用
 
  这里实现弱引用的方法和boost还是有区别的,boost中的弱引用是依赖一个强引用,就是需要有一个智能指针,而这里实现的弱引用和强引用无关,只跟变量和引用对象有关系。不过,如果只靠这两个函数管理变量地址来表示弱引用,代码写起来实在是比较晦涩,即使保证了 add_weak_ref 和 release_weak_ref 成对使用,有时也很难分清一个变量是否变成弱引用了。所以,我们应该像高级语言一样,再封装出一个弱引用对象出来。这时模板就派上用场了,可以写一个弱引用模板把 add_weak_ref 和 release_weak_ref 封装起来。用户可以选择是使用模板还是亲自使用变量。
 
[cpp] view plaincopy
template<typename T> struct TWeakRefPtr  
{  
private:  
    WeakRefObj* m;  
public:  
    TWeakRefPtr(): m(0) { };  
    TWeakRefPtr(const TWeakRefPtr& value): m(0)  
    {  
        if(value.m != 0)  
            value.m->add_weak_ref(&this->m);  
    };  
    TWeakRefPtr(T* ptr_t): m(0)  
    {  
        if(dynamic_cast<WeakRefObj*>(ptr_t) != 0)  
            static_cast<WeakRefObj*>(ptr_t)->add_weak_ref(&this->m);  
    };  
    ~TWeakRefPtr()  
    {  
        if(this->m != 0)  
            this->m->release_weak_ref(&this->m);  
    };  
    operator T*()  
    {  
        return dynamic_cast<T*>(this->m);  
    };  
    operator const T*() const  
    {  
        return dynamic_cast<const T*>(this->m);  
    };  
    TWeakRefPtr& operator =(T* ptr_t)  
    {  
        if(this->m != 0)  
            this->m->release_weak_ref(&this->m);  
        if(dynamic_cast<WeakRefObj*>(ptr_t) != 0)  
        {  
            static_cast<WeakRefObj*>(ptr_t)->add_weak_ref(&this->m);  
        }  
        else  
        {  
            this->m = 0;  
        }  
        return (*this);  
    };  
    TWeakRefPtr& operator =(const TWeakRefPtr& value)  
    {  
        if(this->m != 0)  
            this->m->release_weak_ref(&this->m);  
        if(value.m != 0)  
        {  
            value.m->add_weak_ref(&this->m);  
        }  
        else  
        {  
            this->m = 0;  
        }  
        return (*this);  
    };  
    bool operator ==(const TWeakRefPtr& value) const  
    {  
        return (this->m == value.m);  
    };  
    bool operator ==(T* ptr_t) const  
    {  
        return (this->m == static_cast<WeakRefObj*>(ptr_t));  
    };  
    bool operator !=(const TWeakRefPtr& value) const  
    {  
        return (this->m != value.m);  
    };  
    bool operator !=(T* ptr_t) const  
    {  
        return (this->m != static_cast<WeakRefObj*>(ptr_t));  
    };  
    bool operator <(const TWeakRefPtr& value) const  
    {  
        return (this->m < value.m);  
    };  
    T* operator ->() const  
    {  
        return static_cast<T*>(this->m);  
    };  
};  
  模板没法封装,必须在头文件里写完,虽然代码很多,不过关键功能都是靠 add_weak_ref 和 release_weak_ref 实现,这两个函数的实现代码是隐藏在cpp文件里的,也算是封装了。
 
  如果考虑线程安全,要做的事就多了,最简单的,Windows平台可以用 CRITICAL_SECTION,WeakRefObj对象可以维护一个CRITICAL_SECTION,不仅使管理弱引用变得线程安全,还可以加两个成员函数:
 
  sync_lock() 调用EnterCriticalSection,
 
  sync_unlock() 调用LeaveCriticalSection,
 
  这样顺便让整个对象甚至继承的对象都是线程安全的。
 
  从系统设计上来看,弱引用使代码逻辑看起来比强引用更和谐。强引用管理对象可靠,但是不能克服循环引用的顽疾,弱引用对此是一个弥补。出现循环引用的根本原因是接口内部实现者之间发生了强引用,而这个强引用并不是使用者亲自增加的,所以使用者没把它当做一次引用。从系统设计上来说,应该是只有接口的使用者有权管理强引用,接口的内部实现者如果需要相互引用,应该全都是弱引用。当使用者通过强引用释放接口时,内部实现者通过检查弱引用是否失效作出正确的处理,就可以避免引用循环造成的悲剧。
 
  按照这样的想法,接口的实现者最好既支持强引用又支持弱引用,因此这个WeakRefObj可以继续改进,最后成为一个通用的接口基类interface_type。由于包含了一个 void* _internal 成员变量,最终形成的类不算真正意义上的接口,不过 _internal 是私有且无明确类型,继承后也无法访问到,然后可以通过protected关键字隐藏构造函数和析构函数,使接口公开后既不被能构造也不能被析构,只能通过强引用(引用计数)管理接口的生存时期,同时支持弱引用,这样作为接口基类还勉强可以接受。其实通过重载 new 操作符返回偏移地址,或者像高级语言一样在某个堆空间里保存所有创建出的对象,这个 void* _internal 也是可以消除的,不过由此带来的多线程安全问题和性能下降都很严重,所以就保留现状了。如何去除这个唯一成员变量暂时没思路了。

          

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

评论

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