模板的模板顾名思义就是一个模板函数的参数是另一个模板函数的模板。

模板函数有兴趣的读者请看我上一篇博客模板函数,实现顺序表

请看模板的模板简要举例

wKiom1bqzPqjAUeNAABa09vu3wo286.png

wKiom1bqzRfi_tfDAABaLtP412Y231.png

上边两张图片就是模板的模板类型了,模板的模板也可以使用缺省参数(这一点与函数相似)

wKioL1bqzlaCsQO4AAAb7ewusdU016.png

好了上面介绍过了,现在直接上代码吧,我个人觉得一个函数怎么用,还是直接看实例更容易让人懂,

下面是单链表的节点类, 用的是模板函数

#pragma once
#include<iostream>
using namespace std;

#include<string>

template<typename DataType>
struct SListNode   //单链表的节点
{
	SListNode(DataType x)
		:_data(x),
		_next(NULL)
	{}

	SListNode *_next;
	DataType _data;
};

下面列出单链表类以及主要的函数,也是模板的模板,

template<class DataType, class SListNode = SListNode<DataType> >
class SList
{
public:
	SList();
	SList(const SList&s);
	SList& operator=(SList s);
	~SList();
	void PushBack(DataType x);  //尾插
	void PopBack();  //尾删
	void PushFront(DataType x);
	void PopFront();
	void Insert(const SListNode* pos, DataType x);
	void PrintSList();
	void Clear();

private:
	SListNode*_head;
	SListNode *_tail;
};

下边列出构造函数、赋值运算符重载函数、以及析构函数

template<class DataType, class SListNode = SListNode<DataType> >
SList<DataType, SListNode>::SList()
:_head(NULL),
_tail(NULL)
{}

template<class DataType, class SListNode = SListNode<DataType> >
SList<DataType, SListNode>::SList(const SList&s)
: _head(NULL),
_tail(NULL)
{
	SListNode *cur = s._head;
	while (cur)
	{
		this->PushBack(cur->_data);
		cur = cur->_next;
	}
}

template<class DataType, class SListNode = SListNode<DataType> >
SList<DataType, SListNode>& SList<DataType, SListNode>::operator=(SList s)
{
	swap(_head, s._head);
	swap(_tail, s._tail);
	return *this;
}

//template<class DataType, class SListNode = SListNode<DataType> >
//SList<DataType, SListNode>& SList<DataType, SListNode>::operator=(SList s)
//{
//	if (this != &s)
//	{
//		this->Clear();
//		SListNode *cur = s._head;
//		while (cur)
//		{
//			this->PushBack(cur->_data);
//			cur = cur->_next;
//		}
//	}
//	return *this;
//}


template<class DataType, class SListNode = SListNode<DataType> >
SList<DataType, SListNode>:: ~SList()
{
	Clear();
}

template<class DataType, class SListNode = SListNode<DataType> >
void SList<DataType, SListNode>::Clear()
{
	SListNode* cur = _head;
	while (cur)
	{
		SListNode *del = cur;
		cur = cur->_next;
		delete del;
	}
	_head = NULL;
}

下边列出插入删除函数

template<class DataType, class SListNode = SListNode<DataType> >
void SList<DataType, SListNode>::PushBack(DataType x)
{
	if (_head == NULL)
	{
		_head = new SListNode(x);
		_tail = _head;
		//SList temp(x);//现代写法
		//swap(_head, temp._head);
		//swap(_tail, temp._tail);
	}
	else
	{
		_tail->_next = new SListNode(x);
		_tail = _tail->_next;
	}
}


template<class DataType, class SListNode = SListNode<DataType> >
void SList<DataType, SListNode>::PopBack()
{
	if (_head == NULL)
	{
		cout << "空单链表 " << endl;
		return;
	}
	SListNode*cur = _head;
	while (cur->_next->_next)
	{
		cur = cur->_next;
	}
	_tail = cur;
	delete cur->_next;
	_tail->_next = NULL;
}

template<class DataType, class SListNode = SListNode<DataType> >
void SList<DataType, SListNode>::PushFront(DataType x)
{
	if (_head == NULL)
	{
		PushBack(x);
	}
	SListNode *temp = new SListNode(x);
	temp->_next = _head;
	_head = temp;
}


template<class DataType, class SListNode = SListNode<DataType> >
void SList<DataType, SListNode>::PopFront()
{
	if (_head == NULL)
	{
		cout << "空链表" << endl;
		return;
	}
	SListNode*temp = _head;
	_head = _head->_next;
	delete temp;
}

//template<class DataType, class SListNode = SListNode<DataType> >
//void SList<DataType, SListNode>::Insert(const SListNode* pos, DataType x)
//{
//	if (_head == NULL)
//	{
//		cout << "空链表!" << endl;
//		return;
//	}
//	SListNode *cur = _head;
//	while (cur)
//	{
//		if (cur == pos)
//		{
//			SListNode*temp = new SListNode(x);
//			temp->_next = pos->_next;
//			pos->_next = temp;
//			return;
//		}
//		cur = cur->_next;
//	}
//	cout << "链表中未找到此节点!" << endl;
//}

下边给出输出函数

template<class DataType, class SListNode = SListNode<DataType> >
void SList<DataType, SListNode>::PrintSList()
{
	SListNode*cur = _head;
	while (cur)
	{
		cout << cur->_data << "->";
		cur = cur->_next;
	}
	cout << "NULL" << endl;
}

上边就是主要的函数声明与定义了,单链表内容也是很多的,用作举例,我认为上述的函数就够用了,下边给出测试函数:

#include"SList.h"

void test5()
{
	cout << "使用 int 类型构造 :" << endl;
	cout << "s1:" << endl;
	SList<int> s1;
	s1.PushBack(1);
	s1.PushBack(2);
	s1.PushBack(3);
	s1.PushBack(4);
	s1.PushBack(5);
	s1.PrintSList();
	cout << "拷贝构造 s2:" << endl;
	SList<int> s2(s1);
	s2.PopBack();
	s2.PrintSList();

	cout << "赋值运算符重载 s3:" << endl;
	SList<int> s3;
	s3 = s1;
	s3.PopFront();
	s3.PrintSList();
}

void test6()
{
	cout << "使用 char 类型构造 :" << endl;
	cout << "s1:" << endl;
	SList<char> s1;
	s1.PushBack('a');
	s1.PushBack('b');
	s1.PushBack('c');
	s1.PushBack('d');
	s1.PushBack('e');
	s1.PrintSList();
	cout << " 拷贝构造  s2:" << endl;
	SList<char> s2(s1);
	s2.PopBack();
	s2.PrintSList();

	cout << "赋值运算符重载  s3:" << endl;
	SList<char> s3;
	s3 = s1;
	s3.PopFront();
	s3.PrintSList();
}

void test7()
{
	cout << "使用 string 类型构造 :" << endl;
	cout << "s1:" << endl;
	SList<string> s1;
	s1.PushBack("xxxx");
	s1.PushBack("ssss");
	s1.PushBack("aaaa");
	s1.PushBack("dddd");
	s1.PushBack("eeee");
	s1.PrintSList();
	cout << "拷贝构造  s2:" << endl;
	SList<string> s2(s1);
	s2.PopBack();
	s2.PrintSList();

	cout << "赋值运算符重载  s3:" << endl;
	SList<string> s3;
	s3 = s1;
	s3.PopFront();
	s3.PrintSList();
}

int main()
{
	test5();
	test6();
	test7();

	system("pause");
	return 0;
}

在测试函数里主要测试了基本类型中的int char类型以及非基本类型中的string类型,使用了构造函数、析构函数、赋值运算符重载、插入删除操作,结果如下图

wKiom1bq0RzjUpTJAAAkTnjTPIA168.png

限于我目前的c++水平 仅能实现上述函数,欢迎大家阅读,如发现错误或者不足,恳请您给予批评指正,谢谢!