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 形参名,......> 返回类型   函数名(参数列表)
{
     函数体
}

  其中templateclass 是根本字,这里的class也得用
typename
关键字来取代。<>中之参数叫做模板形参模板形参不能够为空。一旦声明了模版函数,就得就此模板函数的显示参名声明函数中的成员,即于该函数着采取内置类型的地方还足以利用模板形参名。模板函数在调用时,通过沙盘函数的实参来初始化模板形参,一旦编译器确定了实际的模板实参类型就称他实例化了函数模板的一个实例。下面坐swap的模版函数为条例:

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

  当调用这样的沙盘函数时,这里的花色 便见面为调用时之路所代替。比如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 0;
}

result:

图片 1

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 0; }
};

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(8, 3);
    Pair<float> p2(5.5, 2.3);
    cout << p1.Module() << endl;
    cout << p2.Module() << endl;
    system("pause");
    return 0;
}

  result11:

1>------ 已启动生成: 项目: Template specialization, 配置: Debug Win32 ------
1>  TemplateMain.cpp
1>c:\users\administrator\documents\visual studio 2015\projects\suanfa\shiyan1\test1--sequence\template specialization\templatemain.cpp(33): error C2910: “Pair<int>::Module”: 无法显式专用化
1>c:\users\administrator\documents\visual studio 2015\projects\suanfa\shiyan1\test1--sequence\template specialization\templatemain.cpp(38): warning C4305: “参数”: 从“double”到“float”截断
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

  以上之错:error C2910
 提示无法出示专用化,查询C2910错误代码,解决方案:去丢函数Module()实现时前面的
template<>即可;

  可以学习及许多有关变更与错误处理知识的链接:https://msdn.microsoft.com/zh-cn/library/z7kx322x.aspx

  修改后底周转结果如下:

图片 2

 

 

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 == 0;
    }
    bool Full() const {        //判断栈栈是否已满
        return numElements == MAXSIZE;
    }
};

template <class T,int MAXSIZE>
Stack<T, MAXSIZE>::Stack() :numElements(0) {    //初始时栈不含任何元素

}

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 <= 0)
    {
        throw std::out_of_range("Stack<>::pop(),Stack is Empty");
    }
    --numElements;                    //减少元素个数
}

template <class T,int MAXSIZE>
T Stack<T, MAXSIZE>::top() const{
    if (numElements <= 0)
    {
        throw std::out_of_range("Stack<>::pop(),Stack is Empty");
    }
    return elements[numElements - 1];        //返回最后(栈顶)一个元素
}

TemplateDemo.cpp

#include<iostream>
#include<string>
#include"TemplateDemo.h"
using namespace std;
int main() 
{
    try
    {
        Stack<int, 20> int20Stack;        //可以存储20个int类型数据的栈
        Stack<int, 40> int40Stack;        //可以存储40个int类型数据的栈
        Stack<string, 40> string40Stack;    //可以存储40个string类型数据的栈

        //使用存储20个int类型数据的栈
        int20Stack.push(7);
        cout << int20Stack.top() << endl;
        int20Stack.pop();

        //使用可存储40个string类型数据的栈
        string40Stack.push("hello");
        cout << string40Stack.top() << endl;
        string40Stack.pop();
        string40Stack.pop();
        system("pause");
        return 0;
    }
    catch (const std::exception& ex)
    {
        cerr << "Exception: " << ex.what() << endl;
        system("pause");
        return EXIT_FAILURE;        //退出程序且有error标记
    }
}

result:

图片 3