template中友元类的使用

今天尝试用template完成一个循环链表,期间几费周折,将遇到的问题记录一下。这是最后完成的circleList.hpp文件。

#ifndef CIRCLELIST_HPP_
#define CIRCLELIST_HPP_

template <typename T> class CircleList;

template <typename T>
class CNode {
	private:
		T elem;
		CNode<T>* next;
		friend class CircleList<T>;
};

template <typename T>
class CircleList {
	public:
		CircleList();
		~CircleList();
		bool empty() const;
		const T& front() const;
		const T& back() const;
		void advance();
		void add(const T& e);
		void remove();
	private:
		CNode<T>* cursor;
};


template<typename T>
CircleList<T>::CircleList():cursor(NULL){ }

template<typename T>
CircleList<T>::~CircleList()
{
	while(!empty())
		remove();
}

template<typename T>
bool CircleList<T>::empty() const
{
	return cursor == NULL;
}

template<typename T>
const T& CircleList<T>::back() const
{
	return cursor->elem;
}

template<typename T>
const T& CircleList<T>::front() const
{
	return cursor->next->elem;
}

template<typename T>
void CircleList<T>::advance()
{
	cursor = cursor->next;
}

template<typename T>
void CircleList<T>::remove() 
{
	CNode<T>* old = cursor->next;
	if(old == cursor)
		cursor = NULL;
	else
		cursor->next = old->next;
	delete old;
}

template<typename T>
void CircleList<T>::add(const T& e)
{
	CNode<T>* v = new CNode<T>;
	v->elem = e;
	if(cursor == NULL)
	{
		v->next = v;
		cursor = v;
	} else {
		v->next = cursor->next;
		cursor->next = v;
	}
}

#endif

example文件circleTest.cpp

#include <iostream>
#include <string>
#include "circleList.hpp"

using namespace std;

int main()
{
    CircleList<string> list;
    if(list.empty())
        cout << "empty" << endl;

    list.add("hello");
    list.add("world");
    list.add("come on");

    cout << list.front() << endl;
    cout << list.back() << endl;

    return 0;
}

遇到的问题:

(1)开始时,将circleList.hpp 中的类声明和类定义分开放,即类定义在circleList.cpp中,声明在circleList.hpp中。报错,出现undefined reference to的错误。因此,需要复习下类模板的声明、定义和使用。

     (a) 将c++模板的声明和定义都放在同一个文件,如.h和.cpp文件中,使用的时候,#nclude "模板文件名.h或.cpp"即可

       (b) 将c++模板的声明和定义分别放在.h和.cpp文件中,并在.cpp文件中#include .h 文件,使用时,直接#include .cpp文件

       小结:只有将模板.cpp文件同调用.cpp文件,才能确定类的真正类型,不出现undefined reference to一类的链接错误。

(2)代码中标红的地方需要注意,容易忽略。

(3)在模板类中声明友元类,有两种声明方法

      (a) 如circleList.hpp中所示,

template <typename T> class CircleList;

template <typename T>
class CNode {
    private:
        T elem;
        CNode<T>* next;
        friend class CircleList<T>;
};

     此种声明方式,只有当CircleList中数据类型与CNode中的数据类型相同时,友元功能才生效。

     (b)另一种声明方式:

template <typename T>
class CNode {
    private:
        T elem;
        CNode<T>* next;
        template<typename T1> friend class CircleList;
};

   此种声明方式,两个模板类的T和T1不能相同,若相同则出现类型重复的错误。按此种声明方式,无论CircleList中的数据类型是否与CNode相同,都可以访

问CNode类的private成员。

(4)在定义template时,typename和class的区别:在声明时没有区别,typename在使用时有需要注意的地方,未完待续...

          

 

 

posted @ 2013-11-24 21:48  darlwen  阅读(278)  评论(0编辑  收藏  举报