1. 程式人生 > >如何寫出高效C++(模板與泛型程式設計)

如何寫出高效C++(模板與泛型程式設計)

對Effective C++讀了以後的總結(暑假沒事幹。。就是看書,從後往前的總結)

41。瞭解隱式介面和編譯器多型

隱式介面:由一組有效表示式構成,表示式要求了相應的約束條件。

顯式介面:則是在原始碼中明確可見的指出介面的約束條件(比如函式引數的型別)。

所謂的編譯期多型指的是:以不同的templete引數具現化function templates會導致呼叫不同的函式,這就是所謂的編譯期多型。

classes介面是顯式的,多型是通過virtual函式發生於執行期。

template介面是隱式的,多型是通過template具現化和函式過載解析發生於編譯期。

42.瞭解typename的雙重意義

首先了解什麼是巢狀從屬名稱:

template<typename C>

void print2nd(const C& container)

{

   if(container.size() >= 2)

   {

        C::const_iterator iter(container.begin());

        .......

    }

}

像iter這種依賴於template引數C的型別叫做從屬名稱,如果從屬名稱在class內呈巢狀狀,那麼我們稱它為巢狀從屬名稱。

而int這樣與C無關的就叫做非從屬名稱。

因為在知道C之前我們不知道C::const_iterator是不是一個型別,所以說這會導致這變成非有效型別,為了保證他時刻有效,我們需要在塔前main加一個typename,這是class做不到的

一般規則:任何時候你想在template中指涉一個巢狀從屬型別名稱,必須在緊鄰他的前一個位置放上關鍵字typename。

但是,typename不能夠出現在base class lists(基類列)或者member initialization list(成員初值列)內以它作為base class的修飾符。

43.學習處理模板化基類內的名稱

可在derived class templates內通過"this->"指涉base class templates內的成員名稱,或藉由一個明白寫出的"base class 資格修飾符"完成。

例如

template <typename Company>

class LoggingMsgSender::public MsgSender<Company>

{

    public:

    ...

    void sendClearMsg(const MsgInfo& info)

     {

            this->sendClear(info);//假設sendClear被繼承,所以成立,若去掉this,因為無法確切的知道他繼承的MsgSender是一個什麼樣的函式,所以不到函式被具現化之前我們是不知道繼承的類是什麼樣的,也就不知道是否有sendClear函數了

   }

};

44.將與引數無關的程式碼抽離template

因為非型別模板引數而造成的程式碼膨脹往往可以消除,做法是以函式引數或class成員變數替換template引數。

原因:如果是非型別模板引數,比如int,那如果是非引數形式,對於不同的int就要生成不同的一份程式碼,但是其實這樣的程式碼裡面除了int值不同以外其他都相同,那麼就造成了程式碼膨脹,而如果我們另外在類外面寫一個帶有引數的template函式那麼所有的不同的int就只需要一份程式碼。

因為型別引數而造成的程式碼膨脹,往往可降低,做法是讓帶有完全相同二進位制表述的具現型別共享實現碼。

如果你實現某些成員函式而他們操作強型指標(T*),你應該令他們呼叫另一個操作無型別(void*)指標的函式。

45.運用成員函式模板接受所有相容型別

template <typename T>

class SmartPtr

{

public:

 template<typename U>

 SmartPtr(const SmartPtr<U>& other);

}

對任意型別T和任意型別U,可以根據SmartPtr<U>生成一個SmartPtr<T>,因為T有一個建構函式接受一個U引數,也就是根據U物件生成t,也就是泛化拷貝建構函式。

若是要加限制

template <typename T>

class SmartPtr

{

public:

 template<typename U>

 SmartPtr(const SmartPtr<U>& other):heldPtr(other.get()) {...}

 T* get() const { return heldPtr; }

...

private:

T* heldPtr;

};

如果說你要完全掌控copy建構函式或者assignment操作,光是模板還不夠,因為它並不會百分百生成相應,編譯器還是會為你提供相應的函式,所以你需要自己再寫一個複合你自己要求的copy函式和copy assignment操作符。


46.需要型別轉換時請為模板定義非成員函式

template<typename T>

class Rational

{

public:

...

friend const Rational operator*(const Rational& lhs,const Rational& rhs)

{

     return Rational(lhs.numerator()* rhs.numerator(),lhs.deo()*rhs.deo());

}

}

當我們編寫一個class template,而她所提供之“與此template相關的”函式支援“所有引數之型別轉換”時,請將那些函式定義為“class template 內部的friend函式”。

相關推薦

如何高效C++(模板程式設計)

對Effective C++讀了以後的總結(暑假沒事幹。。就是看書,從後往前的總結) 41。瞭解隱式介面和編譯器多型 隱式介面:由一組有效表示式構成,表示式要求了相應的約束條件。 顯式介面:則是在原始碼中明確可見的指出介面的約束條件(比如函式引數的型別)。 所謂的編譯期多

12.29--C++模板程式設計--《C++ Primer》學習

今天學習第16章《模板與泛型程式設計》 感覺腦子有點模模糊糊的,效率不是很高,趕快寫一下學習日誌備忘。 模板其實在java中用的也多了,但是C++的沒用過,感覺有點虛。 其實的確是差不多的用法,所以記幾個點好了。 1. 模板形參表,即template <typename

c++--模板編程

編譯 string std size_t har rom 數組大小 傳遞 成員函數 一、定義模板 1.1 函數模板 1. 適用情況:如果兩個函數幾乎是相同的,唯一的差異是參數的類型,函數體則完全一樣。 2. 定義 template <模板參數列表(以逗號分隔)&g

effective C++筆記--模板程式設計(三)

文章目錄 請使用traits classes表現型別資訊 認識模板超程式設計 請使用traits classes表現型別資訊 . traits並不是C++的關鍵字或是預先定義好的構件,它們是一種技術,也是一個C++程式設計師共同遵守的協議

effective C++筆記--模板程式設計(二)

文章目錄 運用成員函式模板接受所有相容型別 需要型別轉換時請為模板定義非成員函式 運用成員函式模板接受所有相容型別 . 真實指標做的很好的一件事是支援隱式轉換,派生類的指標可以指向基類的指標,指向非常量物件的指標可以指向轉換成常量物件的指

effective C++筆記--模板程式設計(一)

文章目錄 瞭解隱式介面和編譯器多型 瞭解typename的雙重意義 學習處理模板化基類內的名稱 將與引數無關的程式碼抽離template 瞭解隱式介面和編譯器多型 . 面向物件程式設計世界總是以顯式介面和執行期多型解決問題。比

C++面試總結(三)模板程式設計

1.什麼是模板?    泛型程式設計是指獨立與任何型別的方式編寫程式碼。泛型程式設計和麵向物件程式設計,都依賴與某種形式的多型。面向物件程式設計的多型性在執行時應用於存在繼承關係的類,一段程式碼可以可以忽略基類和派生類之間的差異。在泛型程式設計中,編寫的程式碼可以用作多種型別

C/C++基礎--模板程式設計

模板引數 函式模板,編譯器根據實參來為我們推斷模板實參。 模板中可以定義非型別引數,表示一個值而非一個型別,這些值必須是常量表達式,從而允許編譯器在編譯時例項化模板。 非型別引數可以是整型,或者一個指向物件或函式的指標或(左值)引用。繫結到前者的實參必須是常量表達式,繫結到後者的必須具有靜態生存期

《Effective C++》模板程式設計:條款32-條款40

條款41:瞭解隱式介面和編譯期多型 class支援顯示介面和執行期多型 class的顯示介面由函式的名籤式構成(函式名稱、引數型別、返回型別) class的多型通過virtual函式發生在執行期 template支援隱式介面和編譯期多型 templa

C++ primer 模板程式設計

繼續瀏覽c++ primer 看到模板與泛型程式設計這章,就順便把這幾節的程式碼綜合了下,對一個Queue佇列模板的實現 貼一下程式碼(看完書,自己敲,忘記了哪再看下書) #include <ostream> using std::ostream; //宣告Q

C++11(15): 模板程式設計

面向物件程式設計和泛型程式設計都能處理在編寫程式時不知道型別的情況。不同之處:OOP能處理型別在程式執行之前都未知的情況;而泛型程式設計中,在編譯時就能獲知型別了 模板引數類別不能為空。 模板引數表示在類或函式定義中用到的型別或值。 template <typenam

C++primer(第五版)》學習之路-第十六章:模板程式設計

【宣告:版權所有,轉載請標明出處,請勿用於商業用途。聯絡信箱:[email protected]】 16.1 定義模板 1.模板定義以關鍵字template開始,後跟一個模板引數列表,這是一個逗號分隔的一個或多個模板引數的列表,用小於號(<)和大於號(&

模板程式設計(二)--《C++ primer》

 通常在呼叫普通函式時,我們只要做到將函式的宣告放到其定義的前面,保證編譯器先掌握到函式的宣告,因此我們會把其函式宣告放到標頭檔案,而其定義放到原始檔當中;但是模板不同,為了生成一個例項化版本,編譯器需要掌握函式模板或類模板成員函式的定義,所以模板標頭檔案通常既包括宣告

模板程式設計

       當我們希望可以用同一個函式處理不同型別的引數時(比如寫一個加法函式,可以處理各種不同型別的資料)都有哪些方法呢? 1、函式過載(同一作用域;函式名相同;引數列表不同) 缺點:         a、只要有新型別出現,就必須新增對應的函式         b、除了

C++ Primer 第16章】《模板編程》目錄

cnblogs OS pan c++ get In lan microsoft .cn 模板與泛型編程 • 定義模板(16.1) 類模板(16.1.2) 類前置聲明範例 •【C

Effective C++: 07模板編程

單向 不可 允許 non-const 內容 卷標 基類 complete ear C++ template機制自身是一部完整的圖靈機(Turing-complete):它可以被用來計算任何可計算的值。於是導出了模板元編程(TMP, template metaprogramm

Boolan C++ STL編程 二

push_back 使用 功能 lan 鏈表排序 移動元素 直接 雙向鏈表 末尾 本周主要是講解了容器list的使用 List是一種可在常數時間內在任何位置執行插入和刪除操作的順序容器。list是雙向鏈表,其叠代器是雙向的。與其他順序容器(array, vector, d

模板編程1(函數模板

開始 name 對象 AC pan pen != 函數的參數 接受 定義、實例化函數模板: 對於函數體完全相同,唯一差異就是參數類型的情況,我們可以定義一個通用的函數模板,而非為每個類型都定義一個新函數: 1 #include <iostream> 2

C++Primer_Chap16_模板程式設計_List03_過載和模板_筆記

  函式模板可以被另一個模板或普通非模板函式過載。與往常一樣,名字相同的函式必須具有不同數量和型別的引數。涉及函式模板,函式匹配規則會在以下幾方面受到影響: 對於一個呼叫,其候選函式包括所有模板實參推斷成功的函式模板例項 候選的函式模板總是可行的,因為模板實參推斷會排除任何

C++Primer_Chap16_模板程式設計_List02_模板實參推斷_筆記

  從函式實參類確定模板實參的過程稱為模板實參推斷(template argument deduction)。 型別轉換和模板型別引數   如果一個函式形參的型別使用了模板型別引數,那麼它採用特殊的初始化規則。只有很有限的幾種型別轉換會自動應用於這些實參。編譯器通常不是對