• 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;
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    模板形参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 &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 &q);
    	friend ostream & operator<<(ostream &os,const Queue<T> &q){
    		QueueItem<T> *p=q.head;
    	//	Queue *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&);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

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

    Queue<int> l1;
    
    • 1

    模板特化

    可以用模板实参来定做模板类。
    类模板的模板实参通过实例化,构成模板的实例,它是定义好的模板类。
    如果不想使用预定义的类模板来生成模板类,则是以该模板类名自己专门重写一个模板类,则得到模板特化(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();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    实现(只能放在.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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    实验部分

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

    sy3.h

    #ifndef sy3
    #define sy3
    #include 
    #include 
    using namespace std;
    template<class T> 
    class Queue;
    
    template<class T> 
    class QueueItem{
    //public:
    private:
    	T item;
    	QueueItem *next;
    //	friend Queue;
    	friend Queue<T>;
    	QueueItem(const T &t):item(t),next(){}
    //	friend ostream & operator<<(ostream &os,Queue &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 &q);
    	friend ostream & operator<<(ostream &os,const Queue<T> &q){
    		QueueItem<T> *p=q.head;
    	//	Queue *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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150

    sy3.cpp

    #include "sy3.h"
    #include
    #include
    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    main.cpp

    #include 
    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    运行结果:

    在这里插入图片描述

  • 相关阅读:
    安卓搞机教程--修改设置里 添加选项 添加文字 修改图标 修改版本号等等 实例解析
    软件配置 | pip下载第三方库文件及配置pip源的不完全总结
    缓存击穿、缓存穿透、缓存雪崩、反向代理的概念
    设计模式——Decorator(装饰器模式)
    SpringBoot后台管理系统框架
    深度学习入门(十四)数值稳定性和模型初始化
    关系抽取(三)实体关系联合抽取:CasRel
    云仓酒庄北京朝阳区旗舰店发布活动盛况:红酒品鉴沙龙共筑美好
    k8s的资源对象Deployment该如何使用?
    【数据结构】单链表
  • 原文地址:https://blog.csdn.net/zxm_jimin/article/details/126067362