C++模版:

      模版时C++支持多参数多态的工具,使用模版可以为用户为类或函数声明一般模式,使得类的数据成员,或者成员函数的参数,返回值取得任意类型。

模版是一种对类型进行参数化的工具;

通常有两种形式:函数模版和类模版;

函数模板针对仅参数类型不同的函数

       类模板针对仅数据成员成员函数类型不同的类。

注意:模板的声明或定义只能在全局,命名空间或类范围内进行。即不能在局部范围,函数内进行,比如不能在main函数中声明或定义一个模板。

一、函数模板通式


1、函数模板的格式:

    template <class 形参名,class 形参名,......> 返回类型 函数名(参数列表)

   {

      函数体

   }

其中templateclass是关见字,class可以用typename 关见字代替,在这里typename 和class没区别,<>括号中的参数叫模板形参,模板形参和函数形参很相像,模板形参不能为空。一但声明了模板函数就可以用模板函数的形参名声明类中的成员变量和成员函数,即可以在该函数中使用内置类型的地方都可以使用模板形参名。模板形参需要调用该模板函数时提供的模板实参来初始化模板形参,一旦编译器确定了实际的模板实参类型就称他实例化了函数模板的一个实例。比如swap的模板函数形式为

      template <class T> void swap(T& a, T& b){},

当调用这样的模板函数时类型T就会被被调用时的类型所代替,比如swap(a,b)其中abint 型,这时模板函数swap中的形参T就会被int所代替,模板函数就变为swap(int &a, int &b)。而当swap(c,d)其中cddouble类型时,模板函数会被替换为swap(double &a, double &b),这样就实现了函数的实现与类型无关的代码。

  2、注意:对于函数模板而言不存在 h(int,int) 这样的调用,不能在函数调用的参数中指定模板形参的类型,对函数模板的调用应使用实参推演来进行,即只能进行 h(2,3) 这样的调用,或者int a, b; h(a,b)

  函数模板的示例演示将在下文中涉及!

二、类模板通式


  1、类模板的格式为:

    template<class  形参名,class 形参名,…>   class 类名

    { ... };

  类模板和函数模板都是以template开始后接模板形参列表组成,模板形参不能为空,一但声明了类模板就可以用类模板的形参名声明类中的成员变量和成员函数,即可以在类中使用内置类型的地方都可以使用模板形参名来声明。比如

    template<class T> class A{public: T a; T b; T hy(T c, T &d);};

在类A中声明了两个类型为T的成员变量ab,还声明了一个返回类型为T带两个参数类型为T的函数hy

  2、类模板对象的创建:比如一个模板类A,则使用类模板创建对象的方法为A<int> m;在类A后面跟上一个<>尖括号并在里面填上相应的类型,这样的话类A中凡是用到模板形参的地方都会被int 所代替。当类模板有两个模板形参时创建对象的方法为A<int, double> m;类型之间用逗号隔开。

  3、对于类模板,模板形参的类型必须在类名后的尖括号中明确指定。比如A<2> m;用这种方法把模板形参设置为int是错误的(编译错误:error C2079: 'a' uses undefined class 'A<int>'),类模板形参不存在实参推演的问题。也就是说不能把整型值2推演为int 型传递给模板形参。要把类模板形参调置为int 型必须这样指定A<int> m

  4、在类模板外部定义成员函数的方法为:

    template<模板形参列表> 函数返回类型 类名<模板形参名>::函数名(参数列表){函数体},

比如有两个模板形参T1T2的类A中含有一个void h()函数,则定义该函数的语法为:

    template<class T1,class T2> void A<T1,T2>::h(){}。

注意:当在类外面定义类的成员时template后面的模板形参应与要定义的类的模板形参一致。

  5、再次提醒注意:模板的声明或定义只能在全局,命名空间或类范围内进行。即不能在局部范围,函数内进行,比如不能在main函数中声明或定义一个模板。

#include <iostream>

//C++类型模版参数(类型形参,非类型形参,模版形参)
//---------------------------------------------
//----------类型形参----------------
//-------------------------------------------
template<typename T1,typename T2> class A{
public:
T1 show(T1,T2);
A(); }; template<typename T1,typename T2> T1 A<T1,T2>::show(T1 a, T2 b) {return a+b;}
template <typename T1,typename T2> A<T1,T2>::A(){} int main() {
A<int,int> a;
std::cout<<a.show(,)<<std::endl;
return ;
}
 #include <iostream>

 //C++类型模版参数(类型形参,非类型形参,模版形参)
//---------------------------------------------
//-----------非类型形参---------------
//-------------------------------------------
template<typename T1,int a>
class A
{
public:
A();
T1 Some_Show(T1);
}; template<typename T1,int a> A<T1,a>::A(){};
template<typename T1,int a> T1 A<T1,a>::Some_Show(T1 c){return c+a;} int main()
{
A<double,> a;
std::cout<<a.Some_Show(3.5)<<std::endl;
return ;
}
 #ifndef TEMPLATE_DEMO_HXX
#define TEMPLATE_DEMO_HXX template<class T,int MAXSIZE> class Stack{//MAXSIZE由用户创建对象时自行设置
private:
T elems[MAXSIZE]; // 包含元素的数组
int numElems; // 元素的当前总个数
public:
Stack(); //构造函数
void push(T const&); //压入元素
void pop(); //弹出元素
T top() const; //返回栈顶元素
bool empty() const{ // 返回栈是否为空
return numElems == ;
}
bool full() const{ // 返回栈是否已满
return numElems == MAXSIZE;
}
}; template <class T,int MAXSIZE>
Stack<T,MAXSIZE>::Stack():numElems(){ // 初始时栈不含元素
// 不做任何事情
} template <class T,int MAXSIZE>
void Stack<T, MAXSIZE>::push(T const& elem){
if(numElems == MAXSIZE){
throw std::out_of_range("Stack<>::push(): stack is full");
}
elems[numElems] = elem; // 附加元素
++numElems; // 增加元素的个数
} template<class T,int MAXSIZE>
void Stack<T,MAXSIZE>::pop(){
if (numElems <= ) {
throw std::out_of_range("Stack<>::pop(): empty stack");
}
--numElems; // 减少元素的个数
} template <class T,int MAXSIZE>
T Stack<T,MAXSIZE>::top()const{
if (numElems <= ) {
throw std::out_of_range("Stack<>::top(): empty stack");
}
return elems[numElems-]; // 返回最后一个元素
} #endif
 #include<iostream.h>
#include <iostream>
#include <string>
#include <cstdlib>
#include "TemplateDemo.h" int main(){
try {
Stack<int,> int20Stack; // 可以存储20个int元素的栈
Stack<int,> int40Stack; // 可以存储40个int元素的栈
Stack<std::string,> stringStack; // 可存储40个string元素的栈 // 使用可存储20个int元素的栈
int20Stack.push();
std::cout << int20Stack.top() << std::endl; //
int20Stack.pop(); // 使用可存储40个string的栈
stringStack.push("hello");
std::cout << stringStack.top() << std::endl; //hello
stringStack.pop();
stringStack.pop(); //Exception: Stack<>::pop<>: empty stack
return ;
}
catch (std::exception const& ex) {
std::cerr << "Exception: " << ex.what() << std::endl;
return EXIT_FAILURE; // 退出程序且有ERROR标记
}
}

 

类模版参数<T1&>与类模版参数<T1 const&>的区别,传入一个是变量引用,一个是常量直接引用.

四、类模板的默认模板类型形参


  1、可以为类模板的类型形参提供默认值,但不能为函数模板的类型形参提供默认值。函数模板和类模板都可以为模板的非类型形参提供默认值。

  2、类模板的类型形参默认值形式为:template<class T1, class T2=int> class A{};为第二个模板类型形参T2提供int型的默认值。

  3、类模板类型形参默认值和函数的默认参数一样,如果有多个类型形参则从第一个形参设定了默认值之后的所有模板形参都要设定默认值,比如template<class T1=int, class T2>class A{};就是错误的,因为T1给出了默认值,而T2没有设定。

  4、在类模板的外部定义类中的成员时template 后的形参表应省略默认的形参类型。比如template<class  T1, class T2=int> class A{public: void h();}; 定义方法为template<class T1,class T2> void A<T1,T2>::h(){}

定义类模板类型形参:

演示实例1:

  TemplateDemo.h

 #ifndef TEMPLATE_DEMO_HXX
#define TEMPLATE_DEMO_HXX template<class T> class A{
public:
T g(T a,T b);
A();
}; #endif
 #include<iostream.h>
#include "TemplateDemo.h" template<class T> A<T>::A(){} template<class T> T A<T>::g(T a,T b){
return a+b;
} void main(){
A<int> a;
cout<<a.g(,)<<endl;
}
 #ifndef TEMPLATE_DEMO_03
#define TEMPLATE_DEMO_03
//定义带默认类型形参的类模板。这里把T2默认设置为int型。
template<class T1,class T2=int> class CeilDemo{
public:
int ceil(T1,T2);
};
//在类模板的外部定义类中的成员时template 后的形参表应省略默认的形参类型。
template<class T1,class T2>
int CeilDemo<T1,T2>::ceil(T1 a,T2 b){
return a>>b;
} #endif
 #include<iostream.h>
#include "TemplateDemo03.h" void main(){
CeilDemo<int> cd;
cout<<cd.ceil(,)<<endl;
}

从结果我们可以看出,和上例是一样的错误。从实例中我们可以总结如下:类模板如果有多个类型形参,如果使用类型形参默认值则尽量放在参数列表的末尾,而且默认的参数类型必须相同。如果从第一个形参设定了默认值之后的所有模板形参都要设定和第一个形参同类型的默认值。(声明:本人也是刚接触C++,以上只是我经过实例演示对原作者提出的一些质疑,可能我的示例有不到之处,还望大神们不吝赐教,共同完善此博客,给像我一样的菜鸟提供一个学习的平台!)

C++模版详解(-)的更多相关文章

  1. Python3自动化运维之Fabric模版详解

    一.概要 Fabric是基于Python(2.7,3.4+以上版本)实现的SSH命令行工具,简化了SSH的应用程序部署及系统管理任务,它提供了系统基础的操作组件,可以实现本地或远程shell命令,包括 ...

  2. 魔方Newlife.Cube权限系统的使用及模版覆盖详解

    讲人:大石头 时间:2018-11-14 晚上20:00 地点:钉钉群(组织代码BKMV7685)QQ群:1600800 内容:魔方Newlife.Cube权限系统的使用及模版覆盖详解 准备 源码地址 ...

  3. Django模版中加载静态文件配置详解

    .settings.INSTALLED_APPS下添加:django.contrib.staticfiles .settings.py下添加:STATIC_URL = '/static/' . ()在 ...

  4. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  5. DataURL详解--转自格桑blog

    DataURI详解 Posted on 2013 年 09 月 09 日 by admin DataURI,不算新东西,却一直没用过,前些日子在webapp中用了点DataURI,就做了下相关的了解, ...

  6. C++11 std::chrono库详解

    所谓的详解只不过是参考www.cplusplus.com的说明整理了一下,因为没发现别人有详细讲解. chrono是一个time library, 源于boost,现在已经是C++标准.话说今年似乎又 ...

  7. 转AjaxControlToolkit的安装与使用详解

    AjaxControlToolkit的安装与使用详解 AjaxControlToolkit下载http://ajax.asp.net/downloads/default.aspx?tabid=47ht ...

  8. [原创]JavaScript继承详解

    原文链接:http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html 面向对象与基于对象 几乎每个开发人员都有面向对象语言(比如C++. ...

  9. angularjs 指令(directive)详解(1)

    原文地址 什么是directive?我们先来看一下官方的解释: At a high level, directives are markers on a DOM element (such as an ...

随机推荐

  1. java 实现验证码功能

    所需文件以及技术: · SecurityUtil.java   (后面我会复制给大家) · 图像处理技术 · 向客户端输出io流 一,实现的原理,当视图页面加载的时候通过<img >元素的 ...

  2. xlutils模块使用

    python常用模块目录 1.xlutils 实现拷贝原文件 原表格: import xlrd from xlutils.copy import copy workbook = xlrd.open_w ...

  3. 利用Python编写Windows恶意代码!自娱自乐!勿用于非法用途!

    本文主要展示的是通过使用python和PyInstaller来构建恶意软件的一些poc. 利用Python编写Windows恶意代码!自娱自乐!勿用于非法用途!众所周知的,恶意软件如果影响到了他人的生 ...

  4. “Hello World!”团队第五周第七次会议

    博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 八.checkout&push代码 一.会议时间 2017年11月16日  ...

  5. Daily Scrum 11.14

    姓名 今日任务 黄新越 按照热度排序->产生柱状图 刘垚鹏 总体代码架构整合 王骜 总体代码架构整合 林旭鹏 优化整体UI布局 安康 优化整体UI布局 黄伟龙 预先合作编写测试用例 马佐霖 预先 ...

  6. Scrum Meeting 11.03

    成员 今日任务 明日计划 用时 徐越 休息     赵庶宏 编写功能说明书,servlet代码移植 servlet代码移植 3h 薄霖 阅读上一届相关代码,思考改进方法 学习安卓界面设计数据库管理 4 ...

  7. poi读取、通过poi导出数据库的记录到excl表

    package com.nt.test;   import java.io.File; import java.io.FileInputStream; import java.io.FileNotFo ...

  8. 剑指offer:替换空格

    题目描述: 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 思路: 一开始没理解,函数中 ...

  9. week2-作业2

    项目地址:https://git.coding.net/Rainoob/calculate.git ·1.需求分析:程序可以根据输入的参数n随机产生n道四则运算计算题,每个数字在0-100之间.运算符 ...

  10. 数据库:XML,解析Dom4J

    package com.itheima.util; import java.io.FileOutputStream; import java.net.URL; import org.dom4j.Doc ...