クラステンプレートインスタンス(友元メンバー関数テンプレートを含む)
5124 ワード
まず、C++のストリーム入出力はCの標準入出力よりもある程度簡潔であると感じますが、簡単ではありません.私が簡単ではないのは、C++がこのストリーム特性を使用するため、あまり異なるプログラミングパターンが生まれたからです.例えば、友元パターンでは、ストリームクラスの演算子の再ロードは友元しかなく、またストリームクラスはコピーできません.
テンプレートにこの演算子を再ロードするときのパターンはさらに奇妙で、どうせ私は理解していないので、しばらくここまで説明します.結局、C++全体の印象には影響しません!
Queue.h
Source.cpp
テンプレートにこの演算子を再ロードするときのパターンはさらに奇妙で、どうせ私は理解していないので、しばらくここまで説明します.結局、C++全体の印象には影響しません!
Queue.h
#pragma once
#include
#include
using std::ostream;
using std::istream;
template
class QueueItem
{
public:
QueueItem();
~QueueItem();
void setContext(const T & data);
T & getContext();
void setNext(QueueItem * ptr);
QueueItem * getNext();
private:
QueueItem(const QueueItem &);
QueueItem & operator= (const QueueItem &);
private:
T * context;
QueueItem * next;
};
template
class Queue
{
public:
Queue();
Queue(const Queue &);
Queue & operator= (const Queue &);
~Queue();
T & front();
T & back();
void pop();
void push(const T &);
int isEmpty();
friend ostream & operator<< (ostream & os, const Queue & q);
friend istream & operator>> (istream & os, Queue & q);
private:
void destory();
void copyItems(const Queue & other);
private:
QueueItem * head;
QueueItem * tail;
};
template
Queue::Queue()
{
head = nullptr;
tail = nullptr;
}
template
inline Queue::Queue(const Queue & other)
{
head = nullptr;
tail = nullptr;
copyItems(other);
}
template
inline Queue & Queue::operator=(const Queue & other)
{
// TODO: insert return statement here
destory();
copyItems(other);
}
template
inline Queue::~Queue()
{
destory();
}
template
inline T & Queue::front()
{
// TODO: insert return statement here
assert(!isEmpty());
return head->getContext();
}
template
inline T & Queue::back()
{
// TODO: insert return statement here
assert(!isEmpty());
return tail->getContext();
}
template
inline void Queue::pop()
{
if (isEmpty()) return;
auto pTmp = head;
head = head->getNext();
if (isEmpty()) tail = nullptr;
delete pTmp;
pTmp = nullptr;
}
template
inline void Queue::push(const T & data)
{
auto pElem = new QueueItem;
pElem->setContext(data);
pElem->setNext(nullptr);
if (isEmpty()) {
head = tail = pElem;
}
else {
tail->setNext(pElem);
tail = pElem;
}
}
template
inline void Queue::destory()
{
while (!isEmpty()) {
pop();
}
}
template
inline int Queue::isEmpty()
{
return head == nullptr;
}
template
inline void Queue::copyItems(const Queue & other)
{
for (auto p = other->head; p != nullptr; p = p->getNext())
push(p->getContext());
}
template
inline QueueItem::QueueItem()
{
context = new T;
next = nullptr;
}
template
inline QueueItem::~QueueItem()
{
next = nullptr;
delete context;
}
template
inline void QueueItem::setContext(const T & data)
{
*context = data;
}
template
inline T & QueueItem::getContext()
{
return *context;
}
template
inline void QueueItem::setNext(QueueItem* ptr)
{
next = ptr;
}
template
inline QueueItem* QueueItem::getNext()
{
return next;
}
template
ostream & operator<< (ostream & os, const Queue & q)
{
for (auto p = q.head; p!=nullptr; p=p->getNext())
os << p->getContext() << " ";
return os;
}
template
istream & operator>> (istream & os, Queue & q)
{
T tmp;
while (os >> tmp, !os.eof())
q.push(tmp);
return os;
}
Source.cpp
#include
#include
#include "Queue.h"
using namespace std;
void test1()
{
Queue qIntData;
qIntData.push(1);
qIntData.push(2);
qIntData.push(3);
qIntData.push(0);
cout << qIntData << endl;
qIntData.pop();
cout << qIntData << endl;
qIntData.push(4);
cout << qIntData << endl;
}
void test2()
{
Queue qIntData;
cin >> qIntData;
cout << qIntData << endl;
}
int main(int argc, char ** argv)
{
test1();
test2();
return 0;
}