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

时间:2022-05-28 04:42:51

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

本篇文章主要给读者介绍一下关于Queue队列的封装,Queue在数据结构课本上有详细的讲解,它是一种先进先出(FIFO)——先进队列的元素先出队列的数据结构,它的存储方式有线性和环形。它也经常作为程序员面试的题目,在游戏开发 中也经常使用它。以前我们也写过队列的实现,哪些实现方式都是比较简单的初级的,作为我们已经工作多年的程序员,如果还停留在初级阶段,我们就要反思自己了,这么多年,难道自己就没有一点长进?自己收获了什么等等。

     我们都喜欢用别人写的东西,因为人家已经为我们封装好了,无需我们过多考虑,只需调用人家接口就可以实现。很多人并不关心为啥这么实现?这么实现的优点是什么?我们对引擎底层的封装就要站在一个高度去看这个事情,不能就事论事,只满足我自己的需求就可以,而是尽量做到通用,这就要用到模版Template来处理。封装一个类,首先还是要清楚这个类能为开发提供哪些方法?queue类最常用的就是进队列出队列,以及获取队列中功能的元素等等。下面就把商业引擎封装的类给读者展示一下:

template<class TYPE> class Queue
{
public:
/// constructor
Queue();
/// copy constructor
Queue(const Queue<TYPE>& rhs);

/// assignment operator
void operator=(const Queue<TYPE>& rhs);
/// access element by index, 0 is the frontmost element (next to be dequeued)
TYPE& operator[](IndexT index) const;
/// equality operator
bool operator==(const Queue<TYPE>& rhs) const;
/// inequality operator
bool operator!=(const Queue<TYPE>& rhs) const;
/// increase capacity to fit N more elements into the queue
void Reserve(SizeT num);
/// returns number of elements in the queue
SizeT Size() const;
/// return true if queue is empty
bool IsEmpty() const;
/// remove all elements from the queue
void Clear();
/// return true if queue contains element
bool Contains(const TYPE& e) const;

/// add element to the back of the queue
void Enqueue(const TYPE& e);
/// remove the element from the front of the queue
TYPE Dequeue();
/// access to element at front of queue without removing it
TYPE& Peek() const;

protected:
Array<TYPE> queueArray;
};

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
Queue<TYPE>::Queue()
{
// empty
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
Queue<TYPE>::Queue(const Queue<TYPE>& rhs)
{
this->queueArray = rhs.queueArray;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
void
Queue<TYPE>::operator=(const Queue<TYPE>& rhs)
{
this->queueArray = rhs.queueArray;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
TYPE&
Queue<TYPE>::operator[](IndexT index) const
{
return this->queueArray[index];
}

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

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

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
bool
Queue<TYPE>::Contains(const TYPE& e) const
{
return (InvalidIndex != this->queueArray.FindIndex(e));
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
void
Queue<TYPE>::Clear()
{
this->queueArray.Clear();
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
void
Queue<TYPE>::Reserve(SizeT num)
{
this->queueArray.Reserve(num);
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
SizeT
Queue<TYPE>::Size() const
{
return this->queueArray.Size();
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
bool
Queue<TYPE>::IsEmpty() const
{
return this->queueArray.IsEmpty();
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
void
Queue<TYPE>::Enqueue(const TYPE& e)
{
this->queueArray.Append(e);
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
TYPE
Queue<TYPE>::Dequeue()
{
TYPE e = this->queueArray.Front();
this->queueArray.EraseIndex(0);
return e;
}

//------------------------------------------------------------------------------
/**
*/
template<class TYPE>
TYPE&
Queue<TYPE>::Peek() const
{
return this->queueArray.Front();
}

以上就是关于Queue的封装,这样你不论在开发中使用哪些对象都可以使用Queue去实现你想要的功能。其实读者回过头来看看,封装算法没有想象的那么难,做任何事情首先要行动起来,哪怕刚开始写的简陋,至少你已经卖出一步了。