Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

3D游戏引擎底层数据结构的封装之List

$
0
0

笔者介绍:姜雪伟IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。

相信很多开发者在游戏开发中都会用到List表,用于存储数据或者对象。估计也有很多人对它的实现并不清楚,只是会用而已。学习知识不能仅限于表面,如果抱着只是会用,时间长了对自己的技能提升没有任何帮助不进则退,相信大家都学过侯捷先生的书,它编写的C++都是底层的实现。作为开发者来说,如果对知识的掌握只限于表面,长久下去把自己就废了。因为现在引擎都封装的非常完善,其实这样做的后果就是引擎的关键技术只是掌握在少数人手中,大部分开发者都是逻辑程序员,一直要依附于人家才能生活,这样很可悲的,作为开发者的我们更应该自己主动的去学习。这样即使引擎有问题,自己也可以轻松解决。本章主要是给读者介绍关于List的封装,List是链表,表是有结点组成的,链表的遍历可以使用迭代器实现,这些就组成了链表的封装。首先看看迭代器的定义:

 /// the list iterator
    class Iterator
    {
    public:
        /// default constructor
        Iterator();
        /// constructor
        Iterator(Node* node);
        /// copy constructor
        Iterator(const Iterator& rhs);
        /// assignment operator
        const Iterator& operator=(const Iterator& rhs);
        /// equality operator
        bool operator==(const Iterator& rhs) const;
        /// inequality operator
        bool operator!=(const Iterator& rhs) const;
        /// pre-increment operator
        const Iterator& operator++();
        /// post-increment operator
        Iterator operator++(int);
        /// pre-decrement operator
        const Iterator& operator--();
        /// post-increment operator
        Iterator operator--(int);
        /// bool operator
        operator bool() const;
        /// safe -> operator
        TYPE* operator->() const;
        /// safe dereference operator
        TYPE& operator*() const;
    private:
        friend class List<TYPE>;

        /// access to node
        Node* GetNode() const;

        Node* node;
    };

迭代器中还有Node结点指针,下面把节点Node的类定义实现如下所示:

 class Node
    {
        friend class List;
        friend class Iterator;

        /// constructor
        Node(const TYPE& v);
        /// destructor
        ~Node();
        /// set pointer to next node
        void SetNext(Node* n);
        /// get pointer to next node
        Node* GetNext() const;
        /// set pointer to previous node
        void SetPrev(Node* p);
        /// get pointer to previous node
        Node* GetPrev() const;
        /// get value reference
        TYPE& Value();

        Node* next;
        Node* prev;
        TYPE value;
    };

链表有自己的类型,前后指针这些操作都放在链表中,整个List表的实现的完整代码如下所示:

template<class TYPE> class List
{
private:
    class Node;
public:
    class Iterator;

    /// constructor
    List();
    /// copy constructor
    List(const List<TYPE>& rhs);
    /// destructor
    ~List();
    /// assignment operator
    void operator=(const List<TYPE>& rhs);

    /// return true if the list is empty
    bool IsEmpty() const;
    /// get number of elements in list (slow)
    SizeT Size() const;
    /// clear list
    void Clear();
    /// add contents of other list to this list
    void AddList(const List<TYPE>& l);
    /// add element after given element
    Iterator AddAfter(Iterator iter, const TYPE& e);
    /// add element before given element
    Iterator AddBefore(Iterator iter, const TYPE& e);
    /// add element to beginning of list
    Iterator AddFront(const TYPE& e);
    /// add element to end of list
    Iterator AddBack(const TYPE& e);
    /// remove first element of list
    TYPE RemoveFront();
    /// remove last element of list
    TYPE RemoveBack();
    /// remove given element
    TYPE Remove(Iterator iter);
    /// get first element
    TYPE& Front() const;
    /// get last element
    TYPE& Back() const;
    /// get iterator to first element
    Iterator Begin() const;
    /// get iterator past the last element
    Iterator End() const;
    /// find element in array (slow)
    Iterator Find(const TYPE& e, Iterator start) const;

    /// the list iterator
    class Iterator
    {
    public:
        /// default constructor
        Iterator();
        /// constructor
        Iterator(Node* node);
        /// copy constructor
        Iterator(const Iterator& rhs);
        /// assignment operator
        const Iterator& operator=(const Iterator& rhs);
        /// equality operator
        bool operator==(const Iterator& rhs) const;
        /// inequality operator
        bool operator!=(const Iterator& rhs) const;
        /// pre-increment operator
        const Iterator& operator++();
        /// post-increment operator
        Iterator operator++(int);
        /// pre-decrement operator
        const Iterator& operator--();
        /// post-increment operator
        Iterator operator--(int);
        /// bool operator
        operator bool() const;
        /// safe -> operator
        TYPE* operator->() const;
        /// safe dereference operator
        TYPE& operator*() const;
    private:
        friend class List<TYPE>;

        /// access to node
        Node* GetNode() const;

        Node* node;
    };

private:
    /// a node in the list
    class Node
    {
        friend class List;
        friend class Iterator;

        /// constructor
        Node(const TYPE& v);
        /// destructor
        ~Node();
        /// set pointer to next node
        void SetNext(Node* n);
        /// get pointer to next node
        Node* GetNext() const;
        /// set pointer to previous node
        void SetPrev(Node* p);
        /// get pointer to previous node
        Node* GetPrev() const;
        /// get value reference
        TYPE& Value();

        Node* next;
        Node* prev;
        TYPE value;
    };

    Node* front;
    Node* back;
};

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
List<TYPE>::Node::Node(const TYPE& val) :
    next(0),
    prev(0),
    value(val)
{
    // empty
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
List<TYPE>::Node::~Node()
{
    #if NEBULA3_BOUNDSCHECKS
    n_assert(0 == this->next);
    n_assert(0 == this->prev);
    #endif
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
void
List<TYPE>::Node::SetNext(Node* n)
{
    this->next = n;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
typename List<TYPE>::Node*
List<TYPE>::Node::GetNext() const
{
    return this->next;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
void
List<TYPE>::Node::SetPrev(Node* p)
{
    this->prev = p;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
typename List<TYPE>::Node*
List<TYPE>::Node::GetPrev() const
{
    return this->prev;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
TYPE&
List<TYPE>::Node::Value()
{
    return this->value;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
List<TYPE>::Iterator::Iterator() :
    node(0)
{
    // empty
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
List<TYPE>::Iterator::Iterator(Node* n) :
    node(n)
{
    // empty
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
List<TYPE>::Iterator::Iterator(const Iterator& rhs) :
    node(rhs.node)
{
    // empty
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
const typename List<TYPE>::Iterator&
List<TYPE>::Iterator::operator=(const Iterator& rhs)
{
    if (&rhs != this)
    {
        this->node = rhs.node;
    }
    return *this;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
bool
List<TYPE>::Iterator::operator==(const Iterator& rhs) const
{
    return (this->node == rhs.node);
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
bool
List<TYPE>::Iterator::operator!=(const Iterator& rhs) const
{
    return (this->node != rhs.node);
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
const typename List<TYPE>::Iterator&
List<TYPE>::Iterator::operator++()
{
    #if NEBULA3_BOUNDSCHECKS    
    n_assert(0 != this->node);
    #endif
    this->node = this->node->GetNext();
    return *this;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
typename List<TYPE>::Iterator
List<TYPE>::Iterator::operator++(int)
{
    #if NEBULA3_BOUNDSCHECKS
    n_assert(0 != this->node);
    #endif
    Iterator temp(this->node);
    this->node = this->node->GetNext();
    return temp;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
const typename List<TYPE>::Iterator&
List<TYPE>::Iterator::operator--()
{
    #if NEBULA3_BOUNDSCHECKS
    n_assert(0 != this->node);
    #endif
    this->node = this->node->GetPred();
    return *this;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
typename List<TYPE>::Iterator
List<TYPE>::Iterator::operator--(int)
{
    #if NEBULA3_BOUNDSCHECKS
    n_assert(0 != this->node);
    #endif
    Iterator temp(this->node);    
    this->node = this->node->GetPred();
    return temp;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
List<TYPE>::Iterator::operator bool() const
{
    return (0 != this->node);
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
TYPE*
List<TYPE>::Iterator::operator->() const
{
    #if NEBULA3_BOUNDSCHECKS
    n_assert(this->node);
    #endif
    return &(this->node->Value());
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
TYPE&
List<TYPE>::Iterator::operator*() const
{
    #if NEBULA3_BOUNDSCHECKS
    n_assert(this->node);
    #endif
    return this->node->Value();
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
typename List<TYPE>::Node*
List<TYPE>::Iterator::GetNode() const
{
    return this->node;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
List<TYPE>::List() :
    front(0),
    back(0)
{
    // empty
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
List<TYPE>::List(const List<TYPE>& rhs) :
    front(0),
    back(0)
{
    this->AddList(rhs);
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
List<TYPE>::~List()
{
    this->Clear();
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
void
List<TYPE>::operator=(const List<TYPE>& rhs)
{
    this->Clear();
    this->AddList();
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
bool
List<TYPE>::IsEmpty() const
{
    return (0 == this->front);
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
SizeT
List<TYPE>::Size() const
{
    Iterator iter;
    SizeT size = 0;
    for (iter = this->Begin(); iter != this->End(); iter++)
    {
        size++;
    }
    return size;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
void
List<TYPE>::Clear()
{
    while (this->back)
    {
        this->RemoveBack();
    }
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
void
List<TYPE>::AddList(const List<TYPE>& rhs)
{
    Iterator iter;
    for (iter = rhs.Begin(); iter != rhs.End(); iter++)
    {
        this->AddBack(*iter);
    }
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
typename List<TYPE>::Iterator
List<TYPE>::AddAfter(Iterator iter, const TYPE& e)
{
    Node* node = n_new(Node(e));
    if (0 == iter.GetNode())
    {
        #if NEBULA3_BOUNDSCHECKS
        n_assert((0 == this->front) && (0 == this->back));
        #endif
        this->front = node;
        this->back  = node;
    }
    else
    {
        if (iter.GetNode() == this->back)
        {
            this->back = node;
        }
        if (0 != iter.GetNode()->GetNext())
        {
            iter.GetNode()->GetNext()->SetPrev(node);
        }
        node->SetNext(iter.GetNode()->GetNext());
        iter.GetNode()->SetNext(node);
        node->SetPrev(iter.GetNode());
    }
    return Iterator(node);
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
typename List<TYPE>::Iterator
List<TYPE>::AddBefore(Iterator iter, const TYPE& e)
{
    Node *node = n_new(Node(e));
    if (0 == iter.GetNode())
    {
        #if NEBULA3_BOUNDSCHECKS
        n_assert((0 == this->front) && (0 == this->back));
        #endif
        this->front = node;
        this->back = node;
    }
    else
    {
        if (iter.GetNode() == this->front)
        {
            this->front = node;
        }
        if (0 != iter.GetNode()->GetPrev())
        {
            iter.GetNode()->GetPrev()->SetNext(node);
        }
        node->SetPrev(iter.GetNode()->GetPrev());
        iter.GetNode()->SetPrev(node);
        node->SetNext(iter.GetNode());
    }
    return Iterator(node);
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
typename List<TYPE>::Iterator
List<TYPE>::AddFront(const TYPE& e)
{
    return this->AddBefore(this->front, e);
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
typename List<TYPE>::Iterator
List<TYPE>::AddBack(const TYPE& e)
{
    return this->AddAfter(this->back, e);
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
TYPE
List<TYPE>::Remove(Iterator iter)
{
    #if NEBULA3_BOUNDSCHECKS
    n_assert(iter.GetNode());
    #endif
    Node* node = iter.GetNode();
    if (node->GetPrev())
    {
        node->GetPrev()->SetNext(node->GetNext());
    }
    if (node->GetNext())
    {
        node->GetNext()->SetPrev(node->GetPrev());
    }
    if (node == this->front)
    {
        this->front = node->GetNext();
    }
    if (node == this->back)
    {
        this->back = node->GetPrev();
    }
    node->SetNext(0);
    node->SetPrev(0);
    TYPE elm = node->Value();
    n_delete(node);
    return elm;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
TYPE
List<TYPE>::RemoveFront()
{
    #if NEBULA3_BOUNDSCHECKS
    n_assert(0 != this->front);
    #endif
    return this->Remove(this->front);
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
TYPE
List<TYPE>::RemoveBack()
{
    #if NEBULA3_BOUNDSCHECKS
    n_assert(0 != this->back);
    #endif
    return this->Remove(this->back);
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
TYPE&
List<TYPE>::Front() const
{
    #if NEBULA3_BOUNDSCHECKS
    n_assert(0 != this->front);
    #endif
    return this->front->Value();
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
TYPE&
List<TYPE>::Back() const
{
    #if NEBULA3_BOUNDSCHECKS
    n_assert(0 != this->back);
    #endif
    return this->back->Value();
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
typename List<TYPE>::Iterator
List<TYPE>::Begin() const
{
    return Iterator(this->front);
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
typename List<TYPE>::Iterator
List<TYPE>::End() const
{
    return 0;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
typename List<TYPE>::Iterator
List<TYPE>::Find(const TYPE& e, Iterator start) const
{
    for (; start != this->End(); start++)
    {
        if (*start == e)
        {
            return start;
        }
    }
    return 0;
}

学习代码是非常枯燥的,但是知道了它内部的实现原理,使用起来才会更顺手。自己尝试封装一下,再去实现某个小功能,坚持下去,对引擎也会有所了解的。
作者:jxw167 发表于2017/1/18 14:56:28 原文链接
阅读:138 评论:1 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>