程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 解讀C++編程中類模板的三種特化

解讀C++編程中類模板的三種特化

編輯:關於C++

解讀C++編程中類模板的三種特化。本站提示廣大學習愛好者:(解讀C++編程中類模板的三種特化)文章只能為提供參考,不一定能成為您想要的結果。以下是解讀C++編程中類模板的三種特化正文


1.類模板顯式特化
為了停止特化,起首須要一個通用的版本,稱主模板.主模板應用了尺度庫堆算法.  堆 是一種線性化的樹形構造,將一個值壓入一個堆中, 現實上等於將該值拔出到一個樹形構造中;將一個值從堆中掏出就等於移除並前往堆中最年夜值.但在處置字符的指針時會碰壁.堆將依照指針的值停止組織. 我們可以供給一個顯式特化版本處理此成績(例1)假如願望除一個針對const char*的Heap外,還願望供給一個針對char *的Heap;(例2)

//主模板
template <typename T>
class Heap
{
private:
  std::vector<T> h_;
public:
  void push(const T& val);
  T pop();
  bool empty() const //const聲明在末尾表現該函數不克不及修正類變量
  {
    return h_.empty();
  }
}

template <typename T>
void Heap<T>::push(const T& val)
{
  h_.push_back(val);
  std::push_heap(h_.begin(),h_.end());
}

template <typename T>
T Head<T>::pop()
{
  std::pop_head(h_.begin(),h_.end());
  T tmp(h_.back());
  h_.pop_back();
  return tmp;
}

例1

//顯示特化版本
/***********************************************
 *     可以看到模板參數列表是空的,其實這基本不是一個模
 *  板. 由於沒有指定任何模板參數.所以模板的顯式特化又被
 *  稱作"完整特化".
 *     Heap<const char*> 完整特化,不會招致模板的實例化;
 *     Heap<int> 特化,會招致模板的實例化;
 *     編譯器依據主模板的聲明來檢討類模板特化.
***********************************************/
template<>//留意,無任何參數,固然,它原來就不是一個模板
class Head<const char *>
{
private:
  std::vector<const char *> h_;
public:
  void push(const char *pval);
  const char * pop();
  bool empty() const //const聲明在末尾表現該函數不克不及修正類變量
  {
    return h_.empty();
  }
};
//再次提示, Head<const char *>不是一個模板
void Heap<const char*>::push(const char *pval)
{
  h_.push_back(pval);
  std::push_heap(h_.begin(),h_.end());
}

例2

/***********************************************
 *     C++沒有請求顯式特化的接口必需和主模板的接口完整
 *  婚配.如該例中,沒有界說主模板的empty函數,而且自行增長
 *  了size和capitalize兩個函數.
 *     提示:此例中不界說empty函數是弗成取的,界說模板的
 *  顯式特化和類的派生之間固然不存在任何技巧上的接洽,但
 *  是用戶仍然可以參考類的派生的長處,讓特化版本至多具有
 *  主模板的根本才能.
***********************************************/
template<>//留意,無任何參數,固然,它原來就不是一個模板
class Head<char *>
{
private:
  std::vector<char *> h_;
public:
  void push(char *pval);
  char * pop();
  //留意,此處沒有供給empty函數喲!!!
  size_t size() const;
  void capitalize();
};

2.模板部分特化
模板部分特化起首要聲明的是,C++還不支撐對函數模板的部分特化,所以此處我們只評論辯論類模板的部分特化.我們仍然起首須要一個主模板.(參考類模板顯式特化) 自我懂得:假如針對不克不及的指針界說分歧的完整特化,豈不是太費事了,有無更好的方法呢?那就是部分特化了.(例1)提醒: 部分特化它是一個模板.完整特化不是一樣模板.

例1

/***********************************************
 *  部分特化 
 *     和完整特化分歧,這裡的Heap參數類型只是被部門切實其實
 *  定為T*,而T是一個未指定的類型,這就是為何說它是部分
 *  特化的緣由;
 *     當應用一個未經任何潤飾的指針類型來實例化Heap時,
 *  部分特化將優先於主模板;
 *     當應用const char * 或 char *(參考類模板顯式特化)來
 *  實例化Heap時,此時完整特化又會優先於部分特化.
 *  Heap<std::string> h1;  主模板  T是std::string
 *  Heap<std::string *> h2;  部分特化  T是std:string
 *  Heap<int **> h3;    部分特化 T是int *
 *  Heap<char *> h4;  完整特化 T是char *
 *  Heap<const int *> h5;  部分特化 T是const int
 *  Heap<int (*)()> h6;  部分特化 T是int()
***********************************************/
template <typename T>
class Heap<T *> //留意這裡
{
private:
  std::vector<T *>h_;
public:
  void push(const T *val);
  T *pop();
  bool empty()
  {
    return h_.empty();
  }
};

template <typename T>
void Heap<T *>::push(const T *val)
{
  //......
}

例2

/***********************************************
 *     有一點很奧妙但很有效:主模板的完整特化或部分特化
 *  必需采取與主模板雷同數目和類型的實參停止實例化,但它
 *  的模板的參數其實不須要具有和主模板雷同的情勢.
***********************************************/
//界說一個模板,有三個模板參數,書寫情勢以下
template <typename R,typename A1,typename A2> 
//留意,部分特化中,模板參數也是三個,但書寫情勢可紛歧樣喽
class Heap<R (*) (A1,A2)>
{
  //......
};

Heap<char *(*) (int,int)> h7; //R是char *,A1和A2是int
//把 char *(*) (int,int) 想象成一個"指向有兩個參數的非成員函數的指針"

template <class C,typename T>
class Heap<T C::*>
{
  //......
};
Heap<std::string Name::*> h8;//T是string,C是Name

雖然為什麼須要對這些器械應用Heap只是一個猜想,先曉得有這麼一用法吧!

3.類模板成員特化

固然模板的特化和類的派生之間沒有任何干系, 但在特化模板的時刻,無妨自創一下派生的精力.也就意味著一個完整特化或部分特化平日必需從新完成 主模板具有的一切才能.
例:

//主模板
template <typename T>
class Heap
{
private:
  std::vector<T> h_;
public:
  void push(const T& val);
  T pop();
  bool empty() const //const聲明在末尾表現該函數不克不及修正類變量
  {
    return h_.empty();
  }
}
//其實我們真正須要特化的是 push 和 pop兩個函數.
//比較顯式特化,它是經由過程主模板,再寫一個模板顯式特化版本類;
//而這裡只是對類模板成員停止了零丁特化.
template<>
void Heap<const char*>::push(const char *const &pval)
{
  h_.push_back(pval);
  std::push_heap(h_.begin(),h_.end(),strLess);
}

template<>
const char* Heap<const char*>::pop()
{
  std:pop_heap(h_.begin(),h_end(),strLess);
  const char* tmp = h_.back();
  h_.pop_back();
  return tmp;
}


留意,這些函數的接口必需和 "它們正在特化其成員" 的模板的響應接口相婚配.如例1, 就得和主模板的接口相婚配.而假如你是本身再界說的一個顯式/部分特化版本類,就不須要婚配 分歧.(見顯式特化和部分特化),最初指出兩點: 起首,除成員函數外,其實成員也能夠被顯式特化,如靜態成員和成員模板.其次,顯式特化是為模板或模板成員供給定制版本的一種手腕;而顯式實例化僅僅是明白地告知編譯器去實例化一個成員.       

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved