ARPG客户端中场景对象体系设计

一、场景对象体系

二、场景对象生命周期管理

场景对象的生命周期,不适合采用原始的c++管理方式, 即由使用者自己负责删除。而应该采用引用计数方式, 自动负责删除。

采用引用计数方式, 目前用法比较广的分两类:

1、智能指针, 如boost::shared_ptr, 这种方式原理是基于c++对象的生命周期和析构函数来实现的, 而且引用计数是由智能指针对象保存的。在这种方式下, 对象的传递和引用都是使用智能指针对象, 例如:

 class A;
 typedef boost::shared_ptr<A> TAPtr;
 
 //B需要保留对A的引用
 class B
 {
 public:
     void AccessA(TAPtr a)
     {
         m_a = a;
         
         //省略
     };     
 
 private:
     TAPtr m_a;
 };    
 
 //C不需要保留对A的引用, 而仅仅是在某个接口中要访问A
 class C
 {
 public:
     void AccessA(TAPtr a)
     {
         //省略, 访问a
     };  
}; 

 这种方式的优点:

使用者没有任何负担。

缺点:

[1] 效率低。

[2] 不方便暴露对象给lua使用。

2、cocos2d中的Ref方式, 即由对象自身来保存当前的引用数, 并且由对象的使用者自己来负责增加引用数retain和减少引用数release。 在这种方式下, 对象的传递和引用都是使用对象指针来实现, 例如:

 class A: public Ref;
 
 //B需要保留对A的引用
 class B
 {
 public:
    ~B()
    {
        if(m_a)
        {
            m_a.release();
            m_a = NULL;
        }
    }
    
     void AccessA(A *a)
     {
         m_a = a;
         m_a.retain();
         
         //省略
     };     
 
 private:
     A *m_a;
 };    
 
 //C不需要保留对A的引用, 而仅仅是在某个接口中要访问A
 class C
 {
 public:
     void AccessA(A *a)
     {
         //省略, 访问a
     };  
}; 

这种方式的优点是:

[1] 效率高, 无论是传递、访问还是对于引用计数的操作(由使用者本身决定是否要调用retain和release)。

[2] 方便把对象暴露给Lua使用。

缺点是:

增 加了使用者自身的负担, 很容易造成内存泄露, 这正是因为由使用者本身决定是否要调用retain和release引起的。基于相同的原因, 如果要用容器(比如list, vector等)来保存对象时, 标准库中的容器没办法直接使用, 而必须封装, 或者在插入和删除元素是, 手动调用元素的retain和release.

原文地址:https://www.cnblogs.com/zilongblog/p/4208314.html