c++学习笔记3_函数模板的使用并实现自己定义的队列

在这里插入图片描述
实验要求:
熟悉C

1. 函数模板(Function Templates)

重载设计中,最理想的是对不同的参数类型做不同的事情。
比如swap函数,对于任何一个类型T的两个对象a、b,总能调用合适的swap(a,b)——函数模板实现

函数模板的定义:
在这里插入图片描述
关键字template告诉编译器,将要定义一个模板。
<>内的相当于函数的参数列表(模板形参 或 类型参数),每个模板形参都必须加上前缀typenameclass
泛型标识符,例如Typename或T,称为类型参数(Type parameter),这意味这它们类似于变量,但是赋给它们的不能是数字,只能是类型。

例如:

template<class T>
int compare(const T&a,const T&b){
	if(a<b) return -1;
	else if(a>b) return 1;
	else return 0;
} 

模板形参T(T为泛型名),数据形参a、b,函数返回类型int 。

函数模板不是函数,它是以具体的类型参数为实参来生成函数的模板。
函数模板定义被编译时,不会产生任何可执行代码。

类模板(Class Template)

如果让模板来工作,即省心又不降低效率,而且编译器依然可以对代码进行类型检查,还能保持代码的优雅和简洁。

类模板是一种模板,它通过在类定义上铺设类型参数的形式,表示具有相似操作的系列类(类族)。
template< class T> class Queue;中的Queue,即类模板名(class template name),简称模板名(template name)

类模板不是类,而模板类是类。

template<class T> 
class Queue;
template<class T> 
class QueueItem{
//public:
private:
	T item;
	QueueItem *next;
	friend Queue<T>;
	QueueItem(const T &t):item(t),next(){}
//	friend ostream & operator<<(ostream &os,Queue<T> &q);
	friend ostream & operator<<(ostream &os,const Queue<T> &q);
};

template<class T> 
class Queue{
private:
	QueueItem<T> *head;
	QueueItem<T> *tail;
	//friend ostream & operator<<(ostream &os,const Queue<T> &q);
	friend ostream & operator<<(ostream &os,const Queue<T> &q){
		QueueItem<T> *p=q.head;
	//	Queue<T> *p=q.head;
		os<<"< ";
		while(p){
			os<<p->item<<" ";
			p=p->next;
		}
		os<<">"<<endl;
		return os;
	}
	void Destroy();
public:
	Queue():head(0),tail(0){}
	Queue(const Queue<T> &q){
		copyItems(q);
	}
	void push(const T &t);
	void pop();
	bool isEmpty(){
		return head==0;
	}
	T & front(){
		if(!isEmpty()){
			return head->item;
		}
	}
	~Queue(){
		Destroy();
	}
	void copyItems(const Queue<T> &q);

	template<class It>
	void copyItems(It beg,It end);
	template<class It>
	Queue(It beg,It end):head(0),tail(0){
		copyItems(beg,end);
	}
	template<class It>
	void assign(It beg,It end);
	Queue & operator=(const Queue&);
	Queue & operator()(const Queue&);
};

类模板实例化的过程,是根据具体的模板实参,替换成模板形参而产生除对应的模板类的过程。
例如:

Queue<int> l1;

模板特化

可以用模板实参来定做模板类。
类模板的模板实参通过实例化,构成模板的实例,它是定义好的模板类。
如果不想使用预定义的类模板来生成模板类,则是以该模板类名自己专门重写一个模板类,则得到模板特化(template specialization),得到模板特化的过程,称为模板定做(template specializing)

模板定做时, template<> class 类模板名

以下为局部定做(partial specialization)
申明(放在.h文件中) :

template<>
int compare<const char*>(const char * const &v1, const char * const &v2);

template<>
void Queue<const char*>::push(const char* const &t);

template<>
void Queue<const char*>::pop();

实现(只能放在.cpp文件中):

template<>
void Queue<const char*>::push(const char* const &t){
	char *p=new char [strlen(t)+1];
	strncpy(p,t,strlen(t)+1);
	QueueItem<const char*>*qi=new QueueItem<const char*>(p);
	if(isEmpty()){
		head=tail=qi;
	}
	else{
		tail->next=qi;
		tail=qi;
	}
}

template<>
void Queue<const char*>::pop(){
	QueueItem<const char*>*qi=head;
	head=head->next;
	delete[] qi->item;
	delete qi;
}

template<>
int compare<const char*>(const  char* const &a,const  char* const &b){
	return strcmp(a,b);
}

实验部分

(熟悉C++的函数模板的使用并实现自己定义的队列)

sy3.h

#ifndef sy3
#define sy3
#include <iostream>
#include <string.h>
using namespace std;
template<class T> 
class Queue;

template<class T> 
class QueueItem{
//public:
private:
	T item;
	QueueItem *next;
//	friend Queue<T>;
	friend Queue<T>;
	QueueItem(const T &t):item(t),next(){}
//	friend ostream & operator<<(ostream &os,Queue<T> &q);
	friend ostream & operator<<(ostream &os,const Queue<T> &q);
};

template<class T> 
class Queue{
private:
	QueueItem<T> *head;
	QueueItem<T> *tail;
	//friend ostream & operator<<(ostream &os,const Queue<T> &q);
	friend ostream & operator<<(ostream &os,const Queue<T> &q){
		QueueItem<T> *p=q.head;
	//	Queue<T> *p=q.head;
		os<<"< ";
		while(p){
			os<<p->item<<" ";
			p=p->next;
		}
		os<<">"<<endl;
		return os;
	}
	void Destroy();
public:
	Queue():head(0),tail(0){}
	Queue(const Queue<T> &q){
		copyItems(q);
	}
	void push(const T &t);
	void pop();
	bool isEmpty(){
		return head==0;
	}
	T & front(){
		if(!isEmpty()){
			return head->item;
		}
	}
	~Queue(){
		Destroy();
	}
	void copyItems(const Queue<T> &q);

	template<class It>
	void copyItems(It beg,It end);
	template<class It>
	Queue(It beg,It end):head(0),tail(0){
		copyItems(beg,end);
	}
	template<class It>
	void assign(It beg,It end);
	Queue & operator=(const Queue&);
	Queue & operator()(const Queue&);
};



template<class T>
void Queue<T>::push(const T &t){
	QueueItem<T> *pItem = new QueueItem<T>(t);
	if(isEmpty()){
		head=tail=pItem;
	}
	else{
		tail->next=pItem;
		tail=pItem;
	}
}


template<class T>
void Queue<T>::pop(){
	if(isEmpty())
		return;
	QueueItem<T> *p=head;
	head=head->next;
	delete p;
}

template<>
void Queue<const char*>::push(const char* const &t);
template<>
void Queue<const char*>::pop();

template<class T>
void Queue<T>::Destroy(){
	while(!isEmpty()){
		pop();
	}
}
template<class T>
void Queue<T>::copyItems(const Queue<T> &q){
	QueueItem<T> *p=q.head;
	while(p){
		push(p->item);
		p=p->next;
	}
}
template<class T>
template<class It>
void Queue<T>::copyItems(It beg,It end){
	while(beg!=end){
		push(beg);
		beg++;
	}
}

template<class T>
Queue<T> &Queue<T>::operator=(const Queue & q){
	Destroy();
	copyItems(q);
} 
template<class T>
Queue<T> &Queue<T>::operator()(const Queue & q){
	Destroy();
	copyItems(q);
} 
template<class T>
template<class It>
void Queue<T>::assign(It beg,It end){
	Destroy();
	copyItems(beg,end);
}

template<class T>
int compare(const T&a,const T&b){
	if(a<b) return -1;
	else if(a>b) return 1;
	else return 0;
} 
template<>
int compare<const char*>(const  char* const &a,const  char* const &b);

#endif

sy3.cpp

#include "sy3.h"
#include<string>
#include<string.h>
using namespace std;

//类部分模板特化 
template<>
void Queue<const char*>::push(const char* const &t){
	char *p=new char [strlen(t)+1];
	strncpy(p,t,strlen(t)+1);
	QueueItem<const char*>*qi=new QueueItem<const char*>(p);
	if(isEmpty()){
		head=tail=qi;
	}
	else{
		tail->next=qi;
		tail=qi;
	}
}

template<>
void Queue<const char*>::pop(){
	QueueItem<const char*>*qi=head;
	head=head->next;
	delete[] qi->item;
	delete qi;
}

template<>
int compare<const char*>(const  char* const &a,const  char* const &b){
	return strcmp(a,b);
}

main.cpp

#include <iostream>
#include "sy3.h"
using namespace std;

//class Queue 的使用
int main() {
	Queue<int> l1;
	int a=1,b=2,c=3;
	l1.push(a);
	l1.push(b);
	l1.push(c);
	cout<<"l1"<<l1; 
	l1.pop();
	cout<<"l1"<<l1;
	
	Queue<double> l2;
	double d=1.1,e=2.2,f=3.3;
	l2.push(d);
	l2.push(e);
	l2.push(f);
	cout<<"l2"<<l2; 
	double front=l2.front();
	cout<<l2.front()<<endl;
	
	int x[5]={1,2,3,4,5};
	int y[5]={11,12,13,14,15};
	Queue<int> l3(1,4);
	cout<<"l3"<<l3; 
	Queue<double> l4;
	l4.copyItems(l2);
	cout<<"l4"<<l4; 
	
	Queue<int> l5;
	l5.copyItems(11,15);
	cout<<"l5"<<l5; 
	Queue<double> l6;
	l6(l4);
	cout<<"l6"<<l6; 
	Queue<int> l7;
	//l7=l4;
	l7.copyItems(1,3);
	cout<<"l7"<<l7; 	
	cout<<"compare(2,12)"<<compare(2,12)<<endl;
	cout<<"------------------------------------------"<<endl;
	cout<<"compare('ad','ab')"<<compare('ad','ab')<<endl;
	Queue<const char*>q1;
	q1.push("q1");
	q1.push("is");
	q1.push("there");
	cout<<"q1"<<q1;
	q1.pop();
	cout<<"q1"<<q1;
	
/**/	
	Queue<const char*>q2;
	//q2.copyItems(q1);
	q2(q1);
	cout<<"q2"<<q2;
	
	Queue<const char*>q3;
	q3=q1;
	cout<<"q3"<<q2;
	return 0;
}

运行结果:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值