程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++編程新思維中的技巧,編程新思維技巧

C++編程新思維中的技巧,編程新思維技巧

編輯:C++入門知識

C++編程新思維中的技巧,編程新思維技巧


 1.編譯器斷言

技巧大致跟後面的一樣,都是利用偏特化,但是在C++ 0X裡面已經有static_assert,所以感覺這東西也沒什麼用處了,更多的只是開闊眼界   2.偏特化 就是專門對一個類型去進行特殊的處理,畢竟template會給生成所有的類型相同的操作,但是有時候我們需要對特定的幾個類型去處理,於是就有了特化和偏特化   3.局部類 一直被忽略的C++的語法,可以直接在類或者函數裡面定義類,不過一直被忽視就對了,感覺這個還是挺有意思的   4.常數映射為型別: template <int v> struct Int2Type {      enum      {           value = v;      } } 這樣的話,每次用不同的數字去實例化Int2Type,都是不同的類型 書中舉了個反例 復制代碼
 1 <class T,bool flag>
 2 class myclass
 3 {
 4      void DoSomething ()
 5     {
 6           if(flag )
 7          {
 8               T *new_obj = p_old_obj-> clone();
 9          }
10           else
11          {
12               T *new_obj = new T(p_olb_obj );
13          }
14     }
15 };
復制代碼

 

    上面的程序有兩個問題 1.如果T的類型把復制構造函數聲明為private或者protect,則編譯錯誤 2.如果p_old_obj沒事實現clone,則編譯錯誤   我們可以這樣改造下面的程序: 復制代碼
template <class T, bool isPolymorphic >
class NiftyContainer
{
private:
     void DoSomething (T * pobj,int2type <true>)
    {
          T *pNewObj = pobj-> clone();
    }
 
     void DoSomething (T * pobj,int2type <false>)
    {
          T *pNewObj = new T(pobj );
    }
 
public:
     void DoSomething (T * pobj)
    {
         DoSomething(pobj ,int2type< isPolymorhpic>());
    }
};
復制代碼

 

   這樣,只要你的程序有實現clone或者將復制構造函數設置為public,只要符合其中一個條件,就可以編譯通過,而且選擇什麼動作是編譯的時候就決定的 之所以只要實現clone或者public了復制構造函數就可以通過,是因為編譯器不會去編譯一個未用到的類成員函數   5.型別對型別的映射   在我們編程的時候,我們經常需要創建一個函數,用以產生一個新對象
template <class T, class U >
T *create (const U &arg )
{
     return new T( arg);
}

 

   那如果現在需要構造一個widget對象,但是這個對象需要-1作為構造參數,怎麼辦?? 我們可以利用type2type來讓編譯器去選擇我們要使用哪個模板函數   復制代碼
template <class T, class U >
T *create (const U &arg ,type2type< T>)
{
     return new T( arg);
}
 
template <class U>
widgets *create (const & arg,type2type <widgets>)
{
     return new widgets( arg,-1);
}
復制代碼

 

     6,型別選擇 有了前面的基礎,看到後面的幾個也就輕松,原理跟3(型別映射型別差不多) 其實就是利用函數的偏特化機制 復制代碼
template <bool flag, class T ,class U>
struct select
{
     typedef T result;
};
 
template <class T, class U >
struct select <false, T,U >
{
     typedef U result;
};
復制代碼

 

我們可以根據flag來在編譯的時候就決定是要使用T還是使用U類型,不過這本書中的例子是用來選擇是使用指針還是使用普通的類型,感覺這個例子沒有traits好用   7.在編譯期的時候確定一個類型是否可以轉換成為另外一個類型(這樣說感覺不怎麼准確,更准確地說類型是否會隱式轉換為另外一個類型)   復制代碼
template <class T, class U >
class conver
{
     typedef char small;
    
     class big
    {
          char dummy [2];
    };
    
     static small test( U);
    
     static big test(...);
    
     static T makeT();
public:
     enum
    {
          exists = sizeof ( test( makeT() ) ) == sizeof(small )
    };
};
復制代碼

 

  這樣,我們在寫程序的時候,可以直接這樣來判斷一個類是否可以轉換成另外一個類 算起來這個算是我覺得比較有趣的模板技巧了   1.實際上smalltest和bigtest還有makeT都沒有實例化出來,因為sizeof並不會有實例化操作,所以即使沒有定義函數,依然通過編譯   2.多聲明了一個makeT函數是因為一些類會把構造函數聲明為私有的,如果不使用makeT,那麼將無法調用T()   3.模板會尋找最佳匹配條件,也就是說,如果我們再多聲明一個類型Z,把static big test(...)改成static big test(Z),那麼在我們程序編譯的時候,即使兩個類型能夠互相轉換,比如int和size_t,那麼編譯器將會去調用test(Z),這樣將無法看出兩個類是否可以互相轉換,反之,如果test是(...)這樣聲明的,那麼編譯器會認為test(U)比test(...)匹配,於是就去使用test(U)函數   8.type_info的外覆類 這個倒沒什麼,無非就是type_info無法復制,所以重新寫了一個類包裝下   9.定義Nulltype和emptyType復制類 也沒什麼好說的   10.traits 在前面的文章已經說過了 http://www.cnblogs.com/linyilong3/p/3379433.html.   總的來說,要理解這些技巧,需要理解幾點: 1.模板的特化 2.編譯器是通過尋找最合適的匹配選項來匹配選擇實例化的類型    

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