C++ template 学习归纳2

简介:

关于c++中的类模板,常见的形式为:

template<typename T>
class className{
	//...
};

比如笔者在这里举一个例子:

 

#include <iostream>
#include<vector>
#include <stdexcept>

template<typename T>
class stack{
private:
	std::vector<T> elems;
public:
	void push(T const&);
	void pop();
	T top() const;
	bool empty() const{
		return elems.empty();
	}
};

template<typename T>
void stack<T>::push(T const& a){
	elems.push_back(a);
}

template<typename T>
void stack<T>::pop(){
	if(elems.empty()){
		throw std::out_of_range("stack<T>::pop empty");
	}
	return elems.pop_back();
}

template<typename T>
T stack<T>::top()const{
	if(elems.empty()){
		throw std::out_of_range("stack<T>::top empty");
	}
	return elems.back();
}

int main(){

	return 0;
}

从上面的代码可以看出,为了定义成员函数,我们使用了下面的形式,比如:

template<typename T>
void stack<T>::push(T const& a){
	elems.push_back(a);
}

本来在此处有一个问题的,也就是关于类成员函数的实现位置的问题,这个问题我们稍后会提到。

现在我们为了测试上面的例子可以使用下面的函数代码:

int main(){
	stack<int> intStack;
	intStack.push(1);
	intStack.push(2);
	std::cout<<intStack.top()<<std::endl;

	stack<std::string> strStack;
	strStack.push("hello");
	std::cout<<strStack.top()<<std::endl;
	return 0;
}

我们有些时候会遇到这样的代码,比如:

stack<stack<int> > intStack;

在这种情况下,我们要注意就是两个“>”中间的那个空格,那个是必须的,否则的话,编译器会认为是“>>”。这一点大家写代码的时候要注意。

下面我们来看看类模板的特化:

当我们想特化一个类模板的时候,我们就需要用template<>开头,后面更上我们希望特化的代码。比如:

template<>
class myStack<std::string>{
	//...
};

对于特化类模板而言,就如同编写普通的类成员函数一样,比如:

void myStack<int>::pop(int const& a){
	//...
}

下面我们呢来看看类模板的局部特化。

例如对于下面的代码:

template<typename T1,typename T2>
class myClass{
	/...
};

而言,以下几种像是的局部特化都是正确 的:

//局部特化 两个参数一致
template<typename T>
class myClass<T,T>{
	//...
};

//局部特化 第二个为int
template<typename T>
class myClass<T,int>{
	//...
};

//两个参数都为指针类型
template<typename T1,typename T2>
class myClass<T1*,T2*>{
	//...
};

在下面的例子中:

myClass<int float>mif; //将使用<T1,T2>
myClass<float,float>mif; //将使用<T>
myClass<float,int>mif;  //将使用<T,int>
myClass<int*,double*>mp;  //将使用<T1*,T2*>

大家要注意下面的错误代码,

myClass<int,int>m; 
myClass<int*,int*>m;

z这两个代码在上面的这个例子中都是错误的。前者因为会和myClass<T,T>产生二义性。后者会和myClass<T,T>产生二义性、使得编译器不知道应该匹配哪一个。

如果想解决上面的第二个二义性的话,我们可以专门特化下面的代码:

template<typename T>
class myClass<T*,T*>{
	//...
};

接下来我们来看看预设模板参数:

我们先来看看代码再说,大家注意和上面的例子进行比较:

#include <iostream>
#include<vector>
#include <deque>
#include <cstdlib>
#include <stdexcept>

template<typename T,typename CONT=std::vector<T> >
class stack{
private:
	CONT elems;
public:
	void push(T const&);
	void pop();
	T top() const;
	bool empty() const{
		return elems.empty();
	}
};

template<typename T,typename CONT>
void stack<T,CONT>::push(T const& a){
	elems.push_back(a);
}

template<typename T,typename CONT>
void stack<T,CONT>::pop(){
	if(elems.empty()){
		throw std::out_of_range("stack<T>::pop empty");
	}
	return elems.pop_back();
}

template<typename T,typename CONT>
T stack<T,CONT>::top()const{
	if(elems.empty()){
		throw std::out_of_range("stack<T>::top empty");
	}
	return elems.back();
}

int main(){
	try{
		stack<int> intStack;
		stack<double,std::vector<double> > douStack;
		//注意,这里千万不能写下面的这一行代码:
		// stack<double,std::vector<int> > douStack;
		
		intStack.push(1);
		std::cout<<intStack.top()<<std::endl;

		douStack.push(1.1);
		std::cout<<douStack.top()<<std::endl;
	}catch(std::exception const& ex){
		std::cerr<<ex.what()<<std::endl;
		return EXIT_FAILURE;
	}
	return 0;
}

我们使用

	stack<double,std::vector<double> > douStack;

来声明了一个double stack,他的内部使用的是std:Open-mouthed smileeque<>来管理。

image

目录
相关文章
|
3月前
|
JavaScript 前端开发 编译器
模板编译template的背后,究竟发生了什么事?带你了解template的纸短情长
该文章深入探讨了Vue.js中从模板(template)到渲染(render)过程中的编译机制,解释了模板是如何被转化为可执行的渲染函数,并最终呈现为用户界面的全过程。
|
7月前
|
安全 程序员 编译器
【C/C++ 泛型编程 进阶篇 Type traits 】C++类型特征探究:编译时类型判断的艺术
【C/C++ 泛型编程 进阶篇 Type traits 】C++类型特征探究:编译时类型判断的艺术
502 1
|
7月前
|
自然语言处理 编译器 C语言
一文搞懂模板(template)
背景引入: 想象一下,我们要实现一个整数相加,浮点数相加的函数,如果按C语言的思路,我们需要写两个函数名不同的函数,来完成相加;如果C++语言,则可以通过函数重载的特性,写两个函数名相同,但参数列表不同的函数,来完成任务。
88 0
|
存储 Python 容器
py基础知识点归纳总结(上)
py基础知识点归纳总结(上)
110 0
|
机器学习/深度学习 人工智能 自然语言处理
py基础知识点归纳总结(下)
py基础知识点归纳总结(下)
121 0
|
JavaScript 前端开发
细读 ES6 | Class 下篇
ES6 中的继承。
136 0
|
前端开发
前端学习案例3-attribute
前端学习案例3-attribute
75 0
前端学习案例3-attribute
|
前端开发
前端学习案例2-attribute
前端学习案例2-attribute
69 0
前端学习案例2-attribute
|
前端开发
前端学习案例-ref的进阶用法2
前端学习案例-ref的进阶用法2
91 0
前端学习案例-ref的进阶用法2
|
前端开发
前端学习案例-ref的进阶用法1
前端学习案例-ref的进阶用法1
85 0
前端学习案例-ref的进阶用法1