天天看點

C++學習:模闆程式設計(泛型)

C++學習:模闆程式設計

  1. 函數模闆
  2. 類模闆

簡介:

衆所周知,C++這門語言是集面向過程,面向對象,以及泛型程式設計于一體的,之前講了面向過程,面向對象,在這裡,簡單講講泛型程式設計.

泛型:也就是無類型,也就是可以容納支援的所有類型.類似java中的ArrayList集合類一樣,在建立的時候去聲明類型,就可以對該類型的對象進行集中的管理操作.泛型程式設計的出現是為了是解決過多備援的代碼而生,想想如果做一個算法的函數,要支援所有類型的,在沒有泛型之前可能要将所有類型都需要重新寫一遍,那麼如果通過泛型程式設計的話,這個時候就可以大大的降低我們的代碼量.

泛型程式設計是獨立于特定類型的方式的編寫代碼

而模闆用于表達邏輯結構相同,但是具體元素類型不同的資料對象的通用行為

這也就是泛型程式設計的好處,在底層代碼中,泛型的應用是十分廣泛的

模闆是泛型程式設計的基礎;

通過模闆可以快速的建立具有類型安全的類庫集合和函數集合,使用模闆可以操作不同的資料類型,進而避免需要為每一個資料類型産生一個特定的類或者函數

提示:

部落客:章飛_906285288

部落格位址;http://blog.csdn.net/qq_29924041

函數模闆

在之前的文章中,應該有過關于泛型的簡單介紹,在這裡做個統籌彙總,在C++中叫函數模闆,在java中也就直接叫泛型程式設計.

所謂函數模闆:實際上是建立一個通用函數,它所用到的資料的類型(包括傳回值類型、形參類型、局部變量類型)可以不具體指定,而是用一個虛拟的類型來代替(實際上是用一個辨別符來占位),等發生函數調用時再根據傳入的實參來逆推出真正的類型。這個通用函數就稱為函數模闆(Function Template)。

函數模闆的定義類型:

注意:

傳回值類型,形式參數類型,局部變量類型都可以用虛拟類型來代替

定義函數模闆的一般形式為:
template < typename T> 
傳回值類型 函數名 (參數表) {

}
           

或者:

template < class T> 

傳回值類型 函數名 (參數表) {

}
           

如一下函數所示:

#include<iostream>
using namespace::std;

namespace zzf{
  //定義加減乘除的泛型函數模闆,這個時候就不需要判斷類型了,對于對象的話,如果這個對象對這些運算符進行重載過的話,
  //同樣是支援這些運算的
  //template <typename T>
  template <class T>
  T add(T a,T b){
    return a + b;
  }

 template <typename T> 
  T del(T a,T b){
    return a - b;
  }

 template <class T>
  T mul(T a,T b){
    return a * b;
  }

 template <class T>
  T div(T a,T b){
    return a / b;
  }

}

using namespace::zzf; 

int main(int argc,char* argv[]){

  float ret_1 = add(,);
  int ret_2 = add(,);

  cout<<"ret_1:" << ret_1<<endl;
  cout<<"ret_2:" << ret_2<<endl;
  return ;
}
           

在上述的代碼中,采用的就是無類型的泛型函數模闆形式.

類模闆

類模闆使使用者可以為類定義一種模式,使得類中的某些資料成員、某些成員函數的參數、某些成員函數的傳回值能取任意類型,它跟函數模闆類似

類模闆是對一批成員資料類型不同的類的抽象,程式員隻要為這一批類所組成的整個類家族建立一個類模闆,給出一套程式代碼,就可以用來生成多種具體的類

類模闆就是将要處理的對象的類型參數化,是程式能夠處理不同的對象(資料類型)

類模闆的定義

templete <模闆參數表>  //參數表可以是多個
class 類名{
    //類成員聲明
};

//在類模闆以外定義其成員

templete <模闆參數表>
類型名 類名<模闆參數表> ::函數名(參數表){

}
           

對上面的函數進行簡單封裝

/*
 * ===========================================================================
 *
 *       Filename:  caculatorTemplate.h
 *    Description:  
 *        Version:  
 *        Created:  年月日 時分秒
 *       Revision:  none
 *       Compiler:  gcc
 *         Author:   (), 
 *        Company:  
 *
 * ===========================================================================
 */

#ifndef __CACULATORTEMPLATE_H__
#define __CACULATORTEMPLATE_H__

template <class T>
class Caculator{
  public:
    Caculator(){

    }

    T add(T a,T b){
      return a + b;
    }

    T del(T a,T b){
      return a - b;
    }

    T mul(T a,T b){
      return a * b;
    }

    T div(T a,T b){
      return a / b;
    }

    ~Caculator(){

    }

  private:
};

#endif
           

測試代碼

/*
 * ===========================================================================
 *
 *       Filename:  caculatorTemplateTest.cpp
 *    Description:  
 *        Version:  1.0
 *        Created:  2017年06月25日 22時31分22秒
 *       Revision:  none
 *       Compiler:  gcc
 *         Author:   (), 
 *        Company:  
 *
 * ===========================================================================
 */

#include<iostream>
#include"caculatorTemplate.h"
using namespace::std;

int main(int argc,char* argv[]){
 //建立類的執行個體,注意,這個是需要指定類型T的,生成類的模闆
  Caculator<int> cacultor;

  cout<<cacultor.add(,)<<endl;
  return ;
}
           

注意

1:在建立類的模闆時候,是需要去指定具體的類型的

2:類模闆和模闆類的差別:

類模闆是模闆的定義,不是一個實實在在的類,定義中使用的參數是通用類型參數

模闆類是實實在在的類,是類模闆的執行個體化.類中的參數被實際類型所代替

類模闆是模闆,模闆類是類,模闆是使用.類是定義

案例代碼:打造屬于自己的堆棧管理的模闆類

/*
 * ===========================================================================
 *
 *       Filename:  stack.h
 *    Description:  
 *        Version:  1.0
 *        Created:  2017年06月26日 21時48分06秒
 *       Revision:  none
 *       Compiler:  gcc
 *         Author:   (), 
 *        Company:  
 *
 * ===========================================================================
 */

#ifndef __STACK_H__
#define __STACK_H__

namespace zzf{
#include<iostream>
using namespace::std;


template <class T>
class Stack{
  public:
    Stack():top_pointer(){
      array[top_pointer] = ;
    }
    void push(const T& t);
    T pop();
    T getIndexType(int index);
 private:
    //C++中一般使用的是枚舉類型來定義常量
     enum {ssize = };
     T array[ssize];
     int top_pointer;
  };

/* *
 *模闆類必須将定義在頭檔案中
 * */

template <class T>
void Stack<T>::push(const T &t){ 
  if(top_pointer < ){
    cout << "error top_pointer"<<endl;
  }else{
    if(top_pointer < ssize){
        array[top_pointer] = t;
        top_pointer++;
    }
  }
}

template <class T>
T Stack<T>::pop(){
  if(top_pointer < ){
    return array[];
  }else{
    return array[--top_pointer];
  }
}


template<class T>
T Stack<T>::getIndexType(int index){
   if(index < ) {
     cout<<"error index"<<endl;
     return array[];
   } else {
      if(index > top_pointer){
        cout<<"error index"<<endl;
        return array[];
      }else{
        return array[index];
      }
   }
}
}
#endif
           
/*
 * ===========================================================================
 *
 *       Filename:  stackTest.cpp
 *    Description:  
 *        Version:  1.0
 *        Created:  2017年06月26日 21時59分50秒
 *       Revision:  none
 *       Compiler:  gcc
 *         Author:   (), 
 *        Company:  
 *
 * ===========================================================================
 */

#include<iostream>
#include"stack.h"
using namespace::std;
using namespace::zzf;


int main(int argc,char* argv[]){

  Stack<int> stack;

  stack.push();
  stack.push();
  stack.push();
  stack.push();
  stack.push();
  stack.push();
  stack.push();

  cout<<stack.pop()<<endl;
  cout<<stack.getIndexType()<<endl;

  return ;
}
           

注意:

在模闆類中,函數的聲明和定義都需要在頭檔案中進行,否則會出現未定義的引用的錯誤

繼續閱讀