C++模板学习随笔
本文学习内容参考:http://www.cnblogs.com/gw811/archive/2012/10/25/2738929.html
C++模板
1.模板分为函数模板和类模板两种类型
函数模板针对参数类型不同的函数;
类模板针对数据成员和成员函数类型不同的类;
使用模板的目的就是能够让程序员编写与类型无关的代码。比如编写了一个交换两个整型int 类型的swap函数,这个函数就只能实现int 型,对double,字符这些类型无法实现,要实现这些类型的交换就要重新编写另一个swap函数。使用模板的目的就是要让这程序的实现与类型无关,比如一个swap模板函数,即可以实现int 型,又可以实现double型的交换。
注意:模板的声明或定义只能在全局,命名空间或类范围内进行。即不能在局部范围,函数内进行,比如不能在main函数中声明或定义一个模板;
2.函数模板的通用格式如下:
template <class 形参名, class 形参名,......> 返回类型 函数名(参数列表)
{
函数体
}
其中template 和 class 是关键字,这里的class也可以用 typename 关键字来代替。<>中的参数叫做模板形参,模板形参不能为空。一旦声明了模板函数,就可以用模板函数的形参名声明函数中的成员,即在该函数中使用内置类型的地方都可以使用模板形参名。模板函数在调用时,通过模板函数的实参来初始化模板形参,一旦编译器确定了实际的模板实参类型就称他实例化了函数模板的一个实例。下面以swap的模板函数为例:
template <class T> void swap(T& a, T& b){};
当调用这样的模板函数时,这里的类型 T 就会被调用时的类型所替代。比如swap(a , b),当 a 和 b 是 int 时,模板函数swap中的形参 T 就会被 int 所替代,模板函数就变为了swap(int& a, int& b)。而当swap(a , b)中的 a 和 b 为 double 类型时,模板函数就相应地变为了swap(double& a, double& b)。这样也就实现了代码与类型无关。
Demo: 求两个数的最大值的模板函数
#include<iostream>
using namespace std; template <typename T>
const T& max(const T& a, const T& b)
{
return a > b ? a : b;
} int main()
{
cout << max(2.1, 3.3) << endl; //模板实参被隐式推演为double类型
cout << max<double>(2.1, 3.3) << endl; //显示指定实参类型为double
cout << max<int>(2.1, 3.3) << endl; //显示指定实参类型为int
system("pause");
return ;
}
result:
3.类模板的通用格式如下:
template <class 形参名, class 形参名......> class 类名
{
..........
};
3.1类模板和函数模板都是以template开始后接模板形参列表组成,模板形参不能为空,一但声明了类模板就可以用类模板的形参名声明类中的成员变量和成员函数,即可以在类中使用内置类型的地方都可以使用模板形参名来声明。
template <class T>
class Demo
{
T a;
public:
Demo(T first);
T GetValue();
};
3.2类模板的成员函数在类外面实现的定义方式如下(需要在每个方法的实现前面添加 template<class T>):
template <class T>
Demo<T>::Demo(T first){
a=first;
} template <class T>
T Demo<T>::GetValue(){
return a;
}
4.模板特殊化(Template Specialization)(此处学习内容参考http://blog.csdn.net/fingding/article/details/32079289)
4.1模板的特殊化是当模板中的pattern有确定的类型时,模板有一个具体的实现。例如假设我们的类模板pair 包含一个取模计算(module operation)的函数,而我们希望这个函数只有当对象中存储的数据为整型(int)的时候才能工作,其他时候,我们需要这个函数总是返回0。这可以通过下面的代码来实现:
#include<iostream>
using namespace std; template<class T>
class Pair
{
T value1;
T value2;
public:
Pair(T first, T second)
{
value1 = first;
value2 = second;
}
T Module() { return ; }
}; template<>
class Pair<int>
{
int value1;
int value2;
public:
Pair(int first, int second) {
value1 = first;
value2 = second;
}
int Module();
};
//template<> //此处正常情况下需要,但是在VS2015中编译的结果如下result11
int Pair<int>::Module() {
return value1%value2;
} int main()
{
Pair<int> p1(, );
Pair<float> p2(5.5, 2.3);
cout << p1.Module() << endl;
cout << p2.Module() << endl;
system("pause");
return ;
}
result11:
>------ 已启动生成: 项目: Template specialization, 配置: Debug Win32 ------
> TemplateMain.cpp
>c:\users\administrator\documents\visual studio \projects\suanfa\shiyan1\test1--sequence\template specialization\templatemain.cpp(): error C2910: “Pair<int>::Module”: 无法显式专用化
>c:\users\administrator\documents\visual studio \projects\suanfa\shiyan1\test1--sequence\template specialization\templatemain.cpp(): warning C4305: “参数”: 从“double”到“float”截断
========== 生成: 成功 个,失败 个,最新 个,跳过 个 ==========
以上的错误:error C2910 提示无法显示专用化,查询C2910错误代码,解决方案:去掉函数Module()实现时前面的 template<>即可;
可以学习到很多关于生成与错误处理知识的链接:https://msdn.microsoft.com/zh-cn/library/z7kx322x.aspx
修改后的运行结果如下:
5.非类型形参示例(参考:http://www.cnblogs.com/gw811/archive/2012/10/25/2738929.html)
该示例实现的是让用户亲自指定栈的大小,并实现栈的相关操作
TemplateDemo.h
#pragma once
template <class T, int MAXSIZE>class Stack { //MAXSIZE由用户创建对象时自行设定
private:
T elements[MAXSIZE]; //包含栈中元素的数组
int numElements; //当前栈中元素的个数
public:
Stack(); //构造函数
void push(T const&); //压入元素
void pop(); //弹出元素
T top() const; //返回栈顶元素
bool Empty() const { //判断栈是否为空
return numElements == ;
}
bool Full() const { //判断栈栈是否已满
return numElements == MAXSIZE;
}
}; template <class T,int MAXSIZE>
Stack<T, MAXSIZE>::Stack() :numElements() { //初始时栈不含任何元素 } template <class T,int MAXSIZE>
void Stack<T, MAXSIZE>::push(T const& elem) {
if (numElements == MAXSIZE)
{
throw std::out_of_range("Stack<>::push():Stack if fulll");
}
elements[numElements] = elem; //将新元素elem添加到栈中
++numElements; //当前栈中元素个数加1
} template <class T,int MAXSIZE>
void Stack<T, MAXSIZE>::pop() {
if (numElements <= )
{
throw std::out_of_range("Stack<>::pop(),Stack is Empty");
}
--numElements; //减少元素个数
} template <class T,int MAXSIZE>
T Stack<T, MAXSIZE>::top() const{
if (numElements <= )
{
throw std::out_of_range("Stack<>::pop(),Stack is Empty");
}
return elements[numElements - ]; //返回最后(栈顶)一个元素
}
TemplateDemo.cpp
#include<iostream>
#include<string>
#include"TemplateDemo.h"
using namespace std;
int main()
{
try
{
Stack<int, > int20Stack; //可以存储20个int类型数据的栈
Stack<int, > int40Stack; //可以存储40个int类型数据的栈
Stack<string, > string40Stack; //可以存储40个string类型数据的栈 //使用存储20个int类型数据的栈
int20Stack.push();
cout << int20Stack.top() << endl;
int20Stack.pop(); //使用可存储40个string类型数据的栈
string40Stack.push("hello");
cout << string40Stack.top() << endl;
string40Stack.pop();
string40Stack.pop();
system("pause");
return ;
}
catch (const std::exception& ex)
{
cerr << "Exception: " << ex.what() << endl;
system("pause");
return EXIT_FAILURE; //退出程序且有error标记
}
}
result:
C++模板学习随笔的更多相关文章
- typeScript学习随笔(一)
TypeScript学习随笔(一) 这么久了还不没好好学习哈这么火的ts,边学边练边记吧! 啥子是TypeScript TypeScript 是 JavaScript 的一个超集,支持 es6 标准 ...
- (转) 基于Theano的深度学习(Deep Learning)框架Keras学习随笔-01-FAQ
特别棒的一篇文章,仍不住转一下,留着以后需要时阅读 基于Theano的深度学习(Deep Learning)框架Keras学习随笔-01-FAQ
- C#程序集Assembly学习随笔(第一版)_AX
①什么是程序集?可以把程序集简单理解为你的.NET项目在编译后生成的*.exe或*.dll文件.嗯,这个确实简单了些,但我是这么理解的.详细:http://blog.csdn.net/sws8327/ ...
- Hive入门学习随笔(一)
Hive入门学习随笔(一) ===什么是Hive? 它可以来保存我们的数据,Hive的数据仓库与传统意义上的数据仓库还有区别. Hive跟传统方式是不一样的,Hive是建立在Hadoop HDFS基础 ...
- JavaScript ES6 数组新方法 学习随笔
JavaScript ES6 数组新方法 学习随笔 新建数组 var arr = [1, 2, 2, 3, 4] includes 方法 includes 查找数组有无该参数 有返回true var ...
- 64位BASM学习随笔(一)
64位BASM学习随笔(一) Delphi的BASM一直是我最喜爱的内嵌汇编语言,同C/C++的内联汇编相比,它更方便,更具灵活性,由于C/C++的内联汇编仅仅能是或插入式的汇编代码,函数花括号 ...
- XTemplate模板学习和使用总结
XTemplate模板学习和使用总结 前言 XTemplate是我接触的第一个模板语言,用在公司的一个NodeJS项目中,跟它打交道经常是因为需要使用它的语法向模板中注入数据.因为是刚入门前端不久 ...
- jquery学习随笔
转)jquery学习随笔(jquery选择器) jQuery的选择器是CSS 1-3,XPath的结合物.jQuery提取这二种查询语言最好的部分,融合后创造出了最终的jQuery表达式查询语言. ...
- Python学习随笔:使用xlwings设置和操作excel多行多列数据以及设置数据字体颜色填充色对齐方式的方法
☞ ░ 前往老猿Python博文目录 ░ 在前面老猿的文章中,<Python学习随笔:使用xlwings读取和操作Excel文件>.<Python学习随笔:使用xlwings读取和操 ...
随机推荐
- makefile for VCS from Syn@psys
已调试通过 未来将修改成verdi的FSDB版本 下载后把 Makefile_VCS.txt 修改为 Makefile 就可以使用 链接地址: http://files.cnblogs.com/all ...
- virtualenv下配置nginx uwsgi Django
1.安装virtualenv,创建虚拟环境django15 sudo apt-get install virtualenv virtualenv env source bin/active pip i ...
- POJ2250 - Compromise(LCS+打印路径)
题目大意 给定两段文本,问公共单词有多少个 题解 裸LCS... 代码: #include<iostream> #include<string> using namespace ...
- How to Kill All Processes That Have Open Connection in a SQL Server Database[关闭数据库链接 最佳方法] -摘自网络
SQL Server database administrators may frequently need in especially development and test environmen ...
- APNs消息推送完整讲解
在项目的AppDelegate中的didFinishLaunchingWithOptions方法中加入下面的代码: [[UIApplication sharedApplication] registe ...
- js定时显示广告代码
这是一则定时显示广告的javascript代码,当然也可以定时显示某一区块内容,很实用. 代码如下: function strToDate(str, ext) { if (str == null || ...
- Java- Jdbc学习
java jdbc test jsbc: package cn.honji.sqlserver; import java.sql.Connection; import java.sql.ResultS ...
- SCVMM问题汇总
1.在分配虚机到Hyper-V主机时,提示可用内存不足: 可能是虚机分配使用了动态内存,动态内存的最大值太大导致,将其改为固定内存大小即可.
- Android实时监听网络状态(2)
在开发android应用时,涉及到要进行网络访问,时常需要进行网络状态的检查,以提供给用户必要的提醒.一般可以通过ConnectivityManager来完成该工作. ConnectivityMana ...
- 判断2D平面内某点是否在某个旋转的矩形(OBB)内的算法
http://stackoverflow.com/questions/7328424/point-in-obb-oriented-bounding-box-algorithm Given a cent ...