读书人

C++Primer第四版 第十六章的例子关于Q

发布时间: 2013-07-04 11:45:51 作者: rapoo

C++Primer第四版 第十六章的例子关于Queue模版例子的编译问题
QueueItem.h


#pragma once
#include <iostream>
template <class Type> class Queue_;

template <class T>
std::ostream& operator<<(std::ostream&, const Queue_<T>&);

template <class Type>
class QueueItem
{
friend class Queue_<Type>;
friend std::ostream& operator<< <Type>(std::ostream &os, const Queue_<Type> &q); //<Type>要加,不然编译出错
public:
QueueItem();
//~QueueItem();
private:
QueueItem(const Type &t):next(0),item(t){}
Type item;
QueueItem *next;
};

QueueItem.cpp

#include "StdAfx.h"
#include "QueueItem.h"


template <class Type> QueueItem<Type>::QueueItem()
{
}


//template <class type> QueueItem<type>::~QueueItem()
//{
//}

Queue_.h

#pragma once
#include <iostream>
#include "QueueItem.h"

template <class Type>
class Queue_
{
friend std::ostream& operator<< <Type>(std::ostream &os, const Queue_<Type> &q);//<Type>要加,不然编译出错
public:
Queue_(void):head(0),tail(0){}
~Queue_(void){ destroy(); }
Queue_(const Queue_ &q):head(0),tail(0) { copy_elem(q); }
Queue_& operator=(const Queue_ &q);
bool empty() const{ return head == 0; }
void push(const Type &val);
void pop();
Type& front(){ return head->item; }
private:
QueueItem<Type> *head,*tail;
void destroy();
void copy_elem(const Queue_ &q);
};
#include "Queue_.cpp"

Queue_.cpp

#include "StdAfx.h"
#include "Queue_.h"

template <class Type> Queue_<Type>& Queue_<Type>::operator=(const Queue_ &rhs)
{
if (this != &rhs)
{
destroy();
copy_elem(rhs);
}
return *this;
}

template <class Type> void Queue_<Type>::destroy()
{
while(!empty())
{
pop();
}
}

template <class Type> void Queue_<Type>::copy_elem(const Queue_ &orig)
{
QueueItem<Type> *pt;
for (pt = orig.head; pt; pt = pt->next)
{
push(pt->item);
}
}

template <class Type> void Queue_<Type>::push(const Type &val)
{
QueueItem<Type> *pt = new QueueItem<Type>(val);
if (empty())
{
head = tail = pt;
}
else
{
tail->next = pt;
tail = pt;
}

}

template <class Type> void Queue_<Type>::pop()
{
if (!empty())
{
QueueItem<Type> *pt = head;
head = head->next;
delete pt;
}
}

template <class T>
std::ostream& operator<<(std::ostream &os, const Queue_<T> &q)
{


os << "< ";
QueueItem<T> *p;
for (p = q.head; p; p = p->next)
os << p->item << " ";
os <<">";
return os;
}


mainTest.cpp

// Queue.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Queue_.h"

int _tmain(int argc, _TCHAR* argv[])
{
Queue_<int> queue1;
for (int ix = 0; ix != 1024; ++ix)
queue1.push(ix);

std::cout << queue1;
for (int ix = 0; ix != 1024; ++ix) {
int i = queue1.front(); // check next item
if (i != ix)
std::cout << "Something's wrong! i = " << i
<< " ix = " << ix << std::endl;
queue1.pop(); // and remove it
}

if (!queue1.empty())
std::cout << "Queue is not empty but should be!" << std::endl;
else
std::cout << "OK, queue empty again" << std::endl;

for (int ix = 0; ix != 1024; ++ix)
queue1.push(ix);

Queue_<int> queue2(queue1); // use copy constructor

for (int ix = 0; ix != 1024; ++ix) {
int i = queue2.front(); // check next item
if (i != ix)
std::cout << "Something's wrong! i = " << i
<< " ix = " << ix << std::endl;
queue2.pop(); // and remove it
}

if (!queue2.empty())
std::cout << "queue2 is not empty but should be!" << std::endl;
else
std::cout << "OK, queue2 empty again" << std::endl;

queue2 = queue1; // use asssignment operator
for (int ix = 0; ix != 1024; ++ix) {
int i = queue2.front();
if (i != ix)
std::cout << "Something's wrong! i = " << i
<< " ix = " << ix << std::endl;
queue2.pop();
}

if (!queue2.empty())
std::cout << "queue2 is not empty but should be!" << std::endl;
else
std::cout << "OK, queue2 empty again" << std::endl;
return 0;
}


1.所有*.h,*.cpp放在vs2010新建工程下编译通过(Queue_.cpp不要加到工程中去,不然会编译不过)。

问题1:上述代码注释的地方如果去掉注释就报错:如下
>Queue.obj : error LNK2019: unresolved external symbol "public: __thiscall QueueItem<int>::~QueueItem<int>(void)" (??1?$QueueItem@H@@QAE@XZ) referenced in function "public: void * __thiscall QueueItem<int>::`scalar deleting destructor'(unsigned int)" (??_G?$QueueItem@H@@QAEPAXI@Z)
fatal error LNK1120: 1 unresolved externals
想了半天没搞懂哪里错了?求解,问题出在哪里呢


问题2:上面关于Type有段注释,模版函数申明为
template <class T>
std::ostream& operator<<(std::ostream&, const Queue_<T>&);
但是为什么在Queue_头文件中设置友元函数时要加Type呢?
friend std::ostream& operator<< <Type>(std::ostream &os, const Queue_<Type> &q); C++ 类
[解决办法]
因为这是模板的模板,这个友元函数实际是外部函数,是一批函数,不是一个函数;



不是类的成员函数,不能从类模板推导出友元函数。
所以要显式声明为模板函数,参数类型也要显式声明;

这里把所有从这个友元函数推导出的函数,统统声明为模板类的友元函数。

读书人网 >C++

热点推荐