很简单的一个列表类,而且并不是很完善,仅限于在自己的程序中使用。有很多很基本的东西还没搞懂。不过我一直奇怪的是:我将这个类的声明和实现放在不同的文件中时(.h, .cpp),最后在引用用这个类的地方都会出现连接错误,无奈只能将声明和实现放在同一个文件中了(.h),模板类的编译和连接机制到底是怎样的呢?
#pragma once
template<typename NodeType>
class TQueue;
template <typename NodeType>
class QNode
{
public:
NodeType * node;
QNode<NodeType> * nextQNode;
QNode<NodeType> * prevQNode;
friend class TQueue<NodeType>;
};
template <typename NodeType>
class TQueue
{
public:
TQueue(void);
~TQueue(void);
WORD GetCount();
// Queue Behavior
NodeType * PickHead();
void AppendTail(NodeType * _newNode);
BOOL IsEmpty();
// Sequence Visit
NodeType * GetNextNode(HANDLE & hcur);
NodeType * PickCurrentNode(HANDLE & hcur);
private:
WORD _queueLen;
QNode<NodeType> * _queueHead, * _queueTail;
};
/// --- imp --- ///
template <typename NodeType>
TQueue<NodeType>::TQueue(void)
{
_queueLen = 0;
_queueHead = NULL;
_queueTail = NULL;
}
template <typename NodeType>
TQueue<NodeType>::~TQueue(void)
{
NodeType * tmpNode = NULL;
while(_queueLen>0)
{
tmpNode = PickHead();
delete tmpNode;
}
}
template <typename NodeType>
WORD TQueue <NodeType>::GetCount()
{
return _queueLen;
}
// Queue Behavior
template <typename NodeType>
NodeType * TQueue<NodeType>::PickHead()
{
if(_queueLen == 0)return NULL;
assert(_queueHead != NULL);
QNode<NodeType> * tmpQNode = _queueHead;
NodeType * tmpNode = NULL;
if(_queueHead->nextQNode != NULL) // has node lest
{
_queueHead->nextQNode->prevQNode = NULL;
}
else _queueTail = NULL; // no nodes left, so set _queueTail = NULL;
_queueHead = _queueHead->nextQNode;
_queueLen--;
tmpNode = tmpQNode->node;
delete tmpQNode;
return tmpNode;
}
template <typename NodeType>
void TQueue<NodeType>::AppendTail(NodeType * _newNode)
{
QNode<NodeType> * newQNode = new QNode<NodeType>;
newQNode->node = _newNode;
newQNode->nextQNode = NULL;
if(_queueLen == 0) // Empty Queue
{
newQNode->prevQNode = NULL;
_queueHead = newQNode;
_queueTail = newQNode;
_queueLen ++;
return;
}
// Queue not Empty
assert(_queueTail != NULL);
_queueTail->nextQNode = newQNode;
newQNode->prevQNode = _queueTail;
_queueTail = newQNode;
_queueLen ++;
}
template <typename NodeType>
BOOL TQueue<NodeType>::IsEmpty()
{
return (_queueLen==0);
}
// Sequence Visit
template <typename NodeType>
NodeType * TQueue<NodeType>::GetNextNode(HANDLE & hcur)
{
if (hcur == 0x0000)
{
hcur = (HANDLE)_queueHead;
if(_queueHead != NULL) return _queueHead->node;
else return NULL;
}
QNode<NodeType> * tmpQNode = (QNode<NodeType>*)hcur;
if(tmpQNode->nextQNode == NULL)
{
hcur = 0x0000;
return NULL;
}
else
{
hcur = (HANDLE)tmpQNode->nextQNode;
return (tmpQNode->nextQNode->node);
}
}
template <typename NodeType>
NodeType * TQueue<NodeType>::PickCurrentNode(HANDLE & hcur)
{
assert(hcur != NULL);
assert(_queueLen > 0);
QNode<NodeType> * tmpQNode = (QNode<NodeType>*)hcur;
NodeType * tmpNode = NULL;
if (tmpQNode->prevQNode == NULL) // is the head
_queueHead = tmpQNode->nextQNode;
else
tmpQNode->prevQNode->nextQNode = tmpQNode->nextQNode;
if (tmpQNode->nextQNode == NULL) // is the tail
_queueTail = tmpQNode->prevQNode;
else
tmpQNode->nextQNode->prevQNode = tmpQNode->prevQNode;
tmpNode = tmpQNode->node;
delete tmpQNode;
hcur = NULL;
return tmpNode;
}
template<typename NodeType>
class TQueue;
template <typename NodeType>
class QNode
{
public:
NodeType * node;
QNode<NodeType> * nextQNode;
QNode<NodeType> * prevQNode;
friend class TQueue<NodeType>;
};
template <typename NodeType>
class TQueue
{
public:
TQueue(void);
~TQueue(void);
WORD GetCount();
// Queue Behavior
NodeType * PickHead();
void AppendTail(NodeType * _newNode);
BOOL IsEmpty();
// Sequence Visit
NodeType * GetNextNode(HANDLE & hcur);
NodeType * PickCurrentNode(HANDLE & hcur);
private:
WORD _queueLen;
QNode<NodeType> * _queueHead, * _queueTail;
};
/// --- imp --- ///
template <typename NodeType>
TQueue<NodeType>::TQueue(void)
{
_queueLen = 0;
_queueHead = NULL;
_queueTail = NULL;
}
template <typename NodeType>
TQueue<NodeType>::~TQueue(void)
{
NodeType * tmpNode = NULL;
while(_queueLen>0)
{
tmpNode = PickHead();
delete tmpNode;
}
}
template <typename NodeType>
WORD TQueue <NodeType>::GetCount()
{
return _queueLen;
}
// Queue Behavior
template <typename NodeType>
NodeType * TQueue<NodeType>::PickHead()
{
if(_queueLen == 0)return NULL;
assert(_queueHead != NULL);
QNode<NodeType> * tmpQNode = _queueHead;
NodeType * tmpNode = NULL;
if(_queueHead->nextQNode != NULL) // has node lest
{
_queueHead->nextQNode->prevQNode = NULL;
}
else _queueTail = NULL; // no nodes left, so set _queueTail = NULL;
_queueHead = _queueHead->nextQNode;
_queueLen--;
tmpNode = tmpQNode->node;
delete tmpQNode;
return tmpNode;
}
template <typename NodeType>
void TQueue<NodeType>::AppendTail(NodeType * _newNode)
{
QNode<NodeType> * newQNode = new QNode<NodeType>;
newQNode->node = _newNode;
newQNode->nextQNode = NULL;
if(_queueLen == 0) // Empty Queue
{
newQNode->prevQNode = NULL;
_queueHead = newQNode;
_queueTail = newQNode;
_queueLen ++;
return;
}
// Queue not Empty
assert(_queueTail != NULL);
_queueTail->nextQNode = newQNode;
newQNode->prevQNode = _queueTail;
_queueTail = newQNode;
_queueLen ++;
}
template <typename NodeType>
BOOL TQueue<NodeType>::IsEmpty()
{
return (_queueLen==0);
}
// Sequence Visit
template <typename NodeType>
NodeType * TQueue<NodeType>::GetNextNode(HANDLE & hcur)
{
if (hcur == 0x0000)
{
hcur = (HANDLE)_queueHead;
if(_queueHead != NULL) return _queueHead->node;
else return NULL;
}
QNode<NodeType> * tmpQNode = (QNode<NodeType>*)hcur;
if(tmpQNode->nextQNode == NULL)
{
hcur = 0x0000;
return NULL;
}
else
{
hcur = (HANDLE)tmpQNode->nextQNode;
return (tmpQNode->nextQNode->node);
}
}
template <typename NodeType>
NodeType * TQueue<NodeType>::PickCurrentNode(HANDLE & hcur)
{
assert(hcur != NULL);
assert(_queueLen > 0);
QNode<NodeType> * tmpQNode = (QNode<NodeType>*)hcur;
NodeType * tmpNode = NULL;
if (tmpQNode->prevQNode == NULL) // is the head
_queueHead = tmpQNode->nextQNode;
else
tmpQNode->prevQNode->nextQNode = tmpQNode->nextQNode;
if (tmpQNode->nextQNode == NULL) // is the tail
_queueTail = tmpQNode->prevQNode;
else
tmpQNode->nextQNode->prevQNode = tmpQNode->prevQNode;
tmpNode = tmpQNode->node;
delete tmpQNode;
hcur = NULL;
return tmpNode;
}