程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 模板與繼承之藝術——命名模板參數,繼承命名模板參數

模板與繼承之藝術——命名模板參數,繼承命名模板參數

編輯:C++入門知識

模板與繼承之藝術——命名模板參數,繼承命名模板參數


一、命名模板參數 許多模板技術拖著一長串的類型參數,不過很多參數都設有合理的缺省值。 template<typename Policy1 = DefaultPolicy1, typename Policy2 = DefaultPolicy2, typename Policy3 = DefaultPolicy3, typename Policy4 = DefaultPolicy4> class BreadSlicer{};   但是如果我們需要指定某個非缺省實參,還必須明確的指定在它之前的所有實參,即使這些實參跟默認參數一致。 BreadSlicer<DefaultPolicy1, DefaultPolicy2, Custom>   如果我們能夠實現類似BreadSlicer<Policy3 = Custom>顯然更有效率。 思路是這樣的: (1)將參數分派給一個叫做Policy3的東西管理,上面的“=”可以換成模板,將Custom作為模板實參傳遞進去。 這裡我們將Policy3換個名字Policy3_is,然後用Policy3_is<Custom>實現賦值。 (2)將默認實參合並在一起,並用新名字進行索引修改。 class DeafultPolicies{ public:     typedef DefaultPolicy1 P1;//DefaultPolicy1是具體類,P1是為了索引到該類型     typedef DefaultPolicy2 P2;     typedef DefaultPolicy3 P3;     typedef DefaultPolicy4 P4; }; 然後創建類似Policy3_is類進行管理。 template<typename Policy> class Policy1_is : virtual public DefaultPolicies{ //為什麼要虛繼承?待會揭曉     typedef Policy P1;   //將P1從新賦值 }; template<typename Policy> class Policy2_is : virtual public DefaultPolicies{     typedef Policy P2; }; 。。。//剩下的Policy3_is與Policy4_is類似 上面的四個類可以說是修改器,那這些修改器要怎樣安裝,安裝到哪裡呢?要創建一個有四個“插槽”的“插座”。 在這之前首先解決一個問題,默認參數是什麼,根據上面的模式,默認參數應該也從DefaultPolicies繼承而來的。   class DefaultPolicyArgs : virtual public DefaultPolicies{};//默認實參 ”插槽“在插入“修改器”之前應該是被默認實參占領所以,要將四個相同類型(默認實參)同時繼承到一個類裡面就需要使用一點小技巧。   template<typename Base, int D> //使用D將相同的類型編程不同類型,但是類的本質不變,還是子類繼承基類 class D : public Base{}; template<typename T1, typename T2, typename T3, typename T4> class PolicySelector : public D<T1, 1>, public D<T2, 2>, public D<T3, 3>, public D<T4, 4>{}; 此處需要多重繼承所以為了避免產生二義性,前面的“修改器”和默認參數都需要虛繼承 最後就是組裝默認參數。 template<typename PolicySetter1 = DefaultPolicyArgs, typename PolicySetter2 = DefaultPolicyArgs, typename PolicySetter3 = DefaultPolicyArgs, typename PolicySetter4 = DefaultPolicyArgs> class BreadSlicer{     typedef PolicySelector<PolicySetter1, PolicySetter2, PolicySetter3, PolicySetter4> Policies;   //使用Policies::P1索引第一個實參。 }; 就可以直接BreadSlicer<Policy3_is<Custom> > bc; 下面是一個完整的例子。 #include <iostream> #include <list> using namespace std;   class DefaultPolicy1{}; class DefaultPolicy2{}; class DefaultPolicy3{     public:         void print()         {             cout << "我是默認參數3" << endl;         } }; class DefaultPolicy4{};   class DefaultPolicies{    //將默認實參合並     public:         typedef DefaultPolicy1 P1;         typedef DefaultPolicy2 P2;         typedef DefaultPolicy3 P3;         typedef DefaultPolicy4 P4; };   class DefaultPolicyArgs : virtual public DefaultPolicies{};   template <typename Policy> class Policy1_is : virtual public DefaultPolicies{     public:     typedef  Policy P1; };   template<typename Policy> class Policy2_is : virtual public DefaultPolicies{     public:     typedef Policy P2; };   template<typename Policy> class Policy3_is : virtual public DefaultPolicies{     public:     typedef Policy P3; };   template<typename Policy> class Policy4_is : virtual public DefaultPolicies{     public:     typedef Policy P4; };   template<typename Base, int d> class D : public Base{};   template<typename B1, typename B2, typename B3, typename B4> class Selector : public D<B1, 1>, public D<B2, 2>, public D<B3, 3>, public D<B4, 4>{};   template <typename T1 = DefaultPolicyArgs,         typename T2 = DefaultPolicyArgs,         typename T3 = DefaultPolicyArgs,         typename T4 = DefaultPolicyArgs> class BreadSlicer{     typedef Selector<T1, T2, T3, T4> Policies;     public:     void print(){         typename Policies::P3 p3;   //使用其中一個參數類型的例子,                                     //就用的第三個參數來展示吧         p3.print();     } };   class Print3{     public:     void print()     {         cout << "我是客戶參數3" << endl;     } }; int main() {     //BreadSlicer<> b;     BreadSlicer<Policy3_is<Print3> > b;     b.print();     return 0; }      編輯整理:Claruarius,轉載請注明出處。

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