zoukankan      html  css  js  c++  java
  • C++中template的简单用法

      

      模板(Template)指C++程序设计设计语言中采用类型作为参数的程序设计,支持通用程序设计。C++ 的标准库提供许多有用的函数大多结合了模板的观念,如STL以及IO Stream。使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型。

    一、函数模板

      在c++入门中,很多人会接触swap(int&, int&)这样的函数类似代码如下:

    1 void swap(int&a , int& b) {
    2     int temp = a;
    3     a =  b;
    4     b = temp;
    5 }

      但是如果是要支持long,string,自定义class的swap函数,代码和上述代码差不多,只是类型不同,这个时候就是我们定义swap的函数模板,就可以复用不同类型的swap函数代码,函数模板的声明形式如下:

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

      swap函数模板的声明和定义代码如下: 

    1 //method.h
    2 #pragma once
    3 template <class T> void swap(T& t1, T& t2)
    4 {
    5     T tmp;
    6     tmp = t1;
    7     t1 = t2;
    8     t2 = tmp;
    9 }

      上述是模板的声明和定义了,那模板如何实例化呢,模板的实例化是编译器做的事情,与程序员无关,那么上述模板如何使用呢,代码如下:

     1 //main.cpp
     2 #include <stdio.h>
     3 #include "method.h"
     4 int main() {
     5     //模板方法 
     6     int num1 = 1, num2 = 2;
     7     swap<int>(num1, num2);
     8     printf("num1:%d, num2:%d
    ", num1, num2);  
     9     return 0;
    10 }

      可以注意到,我将函数模板的声明和定义都放在了头文件中,一般来说,函数的声明放在头文件,其定义通常是放在源文件中的,这样在包含头文件时,可以有效避免出现重定义error。但模板的使用,需要实例化,而当实例化一个模板时,编译器必须看到模板确切的定义,而不仅仅是它的声明。(这一部分更多的解释可参考http://blog.csdn.net/lichengyu/article/details/6792135

    二、类模板

      考虑我们写一个简单的栈的类,这个栈可以支持int类型,long类型,string类型等等,不利用类模板,我们就要写三个以上的stack类,其中代码基本一样,通过类模板,我们可以定义一个简单的栈模板,再根据需要实例化为int栈,long栈,string栈。

     1 //stack.h
     2 #pragma once
     3 template<class T> class Stack {
     4 public:
     5     Stack();
     6     ~Stack();
     7     void push(T t);
     8     T pop();
     9     bool isEmpty();
    10 private:
    11     T* m_pT;
    12     int m_maxSize;
    13     int m_size;
    14 };
    15 
    16 //同样,也把类模板中函数的定义写在.h文件中
    17 
    18 //Define of Construct
    19 template<class T> Stack<T>::Stack()
    20 {
    21     m_maxSize = 100;
    22     m_size = 0;
    23     m_pT = new T[m_maxSize];
    24 }
    25 
    26 //Define of Destructor
    27 template<class T> Stack<T>::~Stack()
    28 {
    29     delete[] m_pT;
    30 }
    31 
    32 //Define of push()
    33 template<class T> void Stack<T>::push(T t)
    34 {
    35     m_size++;
    36     m_pT[m_size - 1] = t;//数组下标从0开始
    37 }
    38 
    39 //Define of pop()
    40 template<class T> T Stack<T>::pop()
    41 {
    42     T t = m_pT[m_size - 1];
    43     m_size--;
    44     return t;
    45 }
    46 
    47 //Define of isEmpty();
    48 template<class T> bool Stack<T>::isEmpty()
    49 {
    50     return m_size == 0;
    51 }

      上述定义了一个类模板--栈,这个栈很简单,只是为了说明类模板如何使用而已,最多只支持100个元素入栈,使用示例如下:

     1 #include <stdio.h>
     2 #include "stack.h"
     3 
     4 int main()
     5 {
     6     Stack<int> intStack;
     7     intStack.push(1);
     8     intStack.push(2);
     9     intStack.push(3);
    10 
    11     while (!intStack.isEmpty())
    12     {
    13         printf("num:%d
    ", intStack.pop());
    14     }
    15     return 0;
    16 
    17 }
    18 //num:3
    19 //num:2
    20 //num:1

    三、模板参数

      模板可以有类型参数,也可以有非类型参数(即内置类型参数),也可以有模板参数。

      上述类模板的栈有一个限制,就是最多只能支持100个元素,我们可以使用模板参数配置这个栈的最大元素数,如果不配置,就设置默认最大值为100,代码如下:

     1 //stack.h
     2 #pragma once
     3 //模板参数中使用内置的类型参数int,增加栈的最大容纳元素数
     4 template<class T,int maxsize=100> class Stack {
     5 public:
     6     Stack();
     7     ~Stack();
     8     void push(T t);
     9     T pop();
    10     bool isEmpty();
    11 private:
    12     T* m_pT;
    13     int m_maxSize;
    14     int m_size;
    15 };
    16 
    17 //同样,也把类模板中函数的定义写在.h文件中
    18 
    19 //Define of Construct
    20 template<class T,int maxsize> Stack<T,maxsize>::Stack()    //注意Stack<T,maxsize>中maxsize不要漏了
    21 {
    22     m_maxSize =maxsize;
    23     m_size = 0;
    24     m_pT = new T[m_maxSize];
    25 }
    26 
    27 //Define of Destructor
    28 template<class T,int maxsize> Stack<T,maxsize>::~Stack()
    29 {
    30     delete[] m_pT;
    31 }
    32 
    33 //Define of push()
    34 template<class T,int maxsize> void Stack<T,maxsize>::push(T t)
    35 {
    36     m_size++;//增加元素的个数
    37     m_pT[m_size - 1] = t;//入栈,因为数组下标从0开始,所以-1
    38 }
    39 
    40 //Define of pop()
    41 template<class T,int maxsize> T Stack<T,maxsize>::pop()
    42 {
    43     T t = m_pT[m_size - 1];
    44     m_size--;
    45     return t;
    46 }
    47 
    48 //Define of isEmpty();
    49 template<class T,int maxsize> bool Stack<T,maxsize>::isEmpty()
    50 {
    51     return m_size == 0;
    52 }

    使用示例如下:

     1 #include <stdio.h>
     2 #include "stack.h"
     3 
     4 int main()
     5 {
     6     const int maxsize = 1024;
     7     Stack<int,1024> intStack;
     8     for (int i = 0; i < maxsize; i++)
     9         intStack.push(i);
    10 
    11     while (!intStack.isEmpty())
    12     {
    13         printf("num:%d
    ", intStack.pop());
    14     }
    15     return 0;
    16 
    17 }
    18 //num:1023
    19 //num:1022
    20 //num:1021
    21 //...
    22 //...
    23 //num:0

     上述代码中template<class T,int maxsize=100> class Stack{};中int maxsize就是非类型的模板参数。有以下几点需要注意的:

      1、非类型参数在模板定义的内部是常量值,也就是说非类型参数在模板的内部是常量;

      2、非类型模板的参数只能是整型指针引用,像double,String,String **这样的类型是不允许的。但是double &,double *,对象的引用或指针是正确的;

      3、调用非类型模板形参的实参必须是一个常量表达式,即它必须能在编译时计算出结果;

      4、任何局部对象,局部变量,局部对象的地址,局部变量的地址都不是一个常量表达式,都不能用作非类型模板形参的实参。全局指针类型,全局变量,全局对象也不是一个常量表达式,不能用作非类型模板形参的实参。

      5、全局变量的地址或引用,全局对象的地址或引用const类型变量是常量表达式,可以用作非类型模板形参的实参;

      6、sizeof表达式的结果是一个常量表达死,也能用作非类型模板形参的实参。

  • 相关阅读:
    Bridage
    国内项目测试培训笔录和小结
    Proxy
    数据库设计
    PDF转Word
    机务维修成本技术点
    MyEclipse10
    MyEclips:Struts 2 + Hibernate 4 + SQL Server2008
    观察者模式
    javascript事件设计模式
  • 原文地址:https://www.cnblogs.com/codingmengmeng/p/7226666.html
Copyright © 2011-2022 走看看