C++ 函數模板和排序的函數模板——學習筆記

我們在使用重載函數時,只是使用了函數名,而函數體還是得分別定義,在C++中函數模板爲我們很好的解決了這個問題.

1.函數模板的聲明

函數模板可以用來創建一個通用的函數,以支持多種不同的形參,避免重載函數的函數體重複設計。它的最大特點是把函數使用的數據類型作爲參數。

函數模板的聲明形式爲:

template<typename 數據類型參數標識符>

<返回類型><函數名>(參數表)

{

    函數體

}

其中,template是定義模板函數的關鍵字;template後面的尖括號不能省略;typename(或class)是聲明數據類型參數標識符的關鍵字,用來說明它後面的標識符是數據類型標識符。這樣,在以後定義的這個函數中,凡希望根據實參數據類型來確定數據類型的變量,都可以用數據類型參數標識符來說明,從而使這個變量可以適應不同的數據類型。例如:

template<typename T>

T func(T x, int y)

{

    T x;

    //……

}

函數模板只是聲明瞭一個函數的描述即模板,不是一個可以直接執行的函數,只有根據實際情況用實參的數據類型代替類型參數標識符之後,才能產生真正的函數。

關鍵字typename也可以使用關鍵字class,這時數據類型參數標識符就可以使用所有的C++數據類型。

2.模板函數的生成

函數模板的數據類型參數標識符實際上是一個類型形參,在使用函數模板時,要將這個形參實例化爲確定的數據類型。將類型形參實例化的參數稱爲模板實參,用模板實參實例化的函數稱爲模板函數。模板函數的生成就是將函數模板的類型形參實例化的過程。

使用中應注意的幾個問題:

⑴ 函數模板允許使用多個類型參數,但在template定義部分的每個形參前必須有關鍵字typename或class,即:

template<class 數據類型參數標識符1,…,class 數據類型參數標識符n>

<返回類型><函數名>(參數表)

{

     函數體

}

⑵ 在template語句與函數模板定義語句之間不允許有別的語句。如下面的聲明是錯誤的:

template<class T>

int I;

T min(T x,T y)

{

   函數體

}

⑶ 模板函數類似於重載函數,但兩者有很大區別:函數重載時,每個函數體內可以執行不同的動作,但同一個函數模板實例化後的模板函數都必須執行相同的動作 
       
3. 函數模板的異常處理
 

 函數模板中的模板形參可實例化爲各種類型,但當實例化模板形參的各模板實參之間不完全一致時,就可能發生錯誤,C++中,函數模板與同名的非模板函數重載時,應遵循下列調用原則:

• 尋找一個參數完全匹配的函數,若找到就調用它。若參數完全匹配的函數多於一個,則這個調用是一個錯誤的調用。

• 尋找一個函數模板,若找到就將其實例化生成一個匹配的模板函數並調用它。

• 若上面兩條都失敗,則使用函數重載的方法,通過類型轉換產生參數匹配,若找到就調用它。

•若上面三條都失敗,還沒有找都匹配的函數,則這個調用是一個錯誤的調用。

在前期做了一份sort(),qsort()的用法分析,鏈接如下:

http://blog.csdn.net/zzzmmmkkk/archive/2009/06/13/4266888.aspx

但是qsort()需要自己編寫一個比較器函數,同時不支持C++集合類,那麼就可以自己編寫一個模板函數來實現.

4.排序函數模板的實現

該函數模板使用冒泡法對集合元素進行排序,參數說明:
     collection        集合對象,集合對象必須提供 [] 操作。
     element          集合元素,該參數的作用僅僅是確定集合元素類型,參數的值沒有用,建議取集合的第一個元素。集合元素必須提供複製、賦值和比較操作。
      count            集合元素的數目
      ascend          表明排序時使用升序(true)還是降序(false)
    該函數模板支持C++數組以及MFC集合CStringArray、CArray。

代碼如下:

template  <typename COLLECTION_TYPE,typename ELEMENT_TYPE>   
  void   BubbleSort(COLLECTION_TYPE collection[],ELEMENT_TYPE element,int count,bool ascend=true)   
  {   
   int j,element_flag;
   int k=count-1;
   while(k>0)
   {
        element_flag=0;
        for(j=element;j<k;j++)
          {
            if(ascend)
             {
               if(collection  [j]   >   collection [j+1])
               {
                    COLLECTION_TYPE temp=collection  [j];   
                    collection [j]   =  collection  [j+1];   
                    collection  [j+1]   =   temp;  
                    element_flag=j;
               }
             }
           else
           {
               if(collection  [j]   <  collection [j+1])
                {
                     COLLECTION_TYPE temp=collection  [j];   
                     collection [j]   =  collection  [j+1];   
                     collection  [j+1]   =   temp;  
                     element_flag=j;
     
                 }
            }
         }
    k=element_flag;

}

}  

利用它對整型數組進行排序,

int ArrayInt[]={29,12,4,34,56,0,8,6,18,32};

BubbleSort(ArrayInt,0,10,false);//如果省去false講按默認的true排列

對整數集合按升序排序: 

CArray <int, int> collectionInt;
      collectionInt.Add(34);
      collectionInt.Add(90);
      collectionInt.Add(6);
      collectionInt.Add(91);
      collectionInt.Add(37);
      collectionInt.Add(21);
      collectionInt.Add(187);
      BubbleSort(collectionInt, collectionInt[0],
collectionInt.GetSize());

對字符串數組的排列:

string arrayString[4] = {"jackjones", "lee", "levi's","boss"};

BubbleSort(arrayString,0,4,false);

對一個字符串集合按降序排序: 
            CStringArray collectionString;
            collectionString.Add("jackjones");
            collectionString.Add("lee");
            collectionString.Add("levi's");

            collectionString.Add("boss");
           BubbleSort(collectionString, collectionString[0],

collectionString.GetSize(), false);

http://blog.csdn.net/zzzmmmkkk/article/details/4285026

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章