一、命名模闆參數:
有些進階腳本語言,如Perl、PL/SQL等,他們的函數參數在調用時都支援命名參數,既在調用時可以不按照順序傳遞參數,而是p可以按照參數的名字傳遞。先看下面的代碼示例:
template<typename Policy1 = DefaultPolicy1,
typename Policy2 = DefaultPolicy2,
typename Policy3 = DefaultPolicy3,
typename Policy4 = DefaultPolicy4>
class BreadSlicer {
... ...
}
上面的模闆類含有4個模闆參數,如果要想指定其中的某個參數不為預設參數,那麼也必須同時指定其之前的所有模闆參數,如:
BreadSlicer<DefaultPolicy1,DefaultPolicy2,Custom>,然而我們更希望使用這樣的調用形式:BreadSlicer<Policy3 = Custom>。下面将給出一些具體的實作,請務必留意代碼中的關鍵性注釋:
1 #include <stdio.h>
2 #include <typeinfo>
3 #include <conio.h>
4
5 //先定義出不同的政策類。
6 class DefaultPolicy1 {};
7 class DefaultPolicy2 {};
8 class DefaultPolicy3 {};
9 class DefaultPolicy4 {};
10
11 //該類将會是所有Policy Class的基類。他提供了預設的四個Policy的類型重定義。
12 //是以在預設情況下,這四個Policy将會是BreadSlicer的四個Policy。
13 class DefaultPolicies {
14 public:
15 typedef DefaultPolicy1 P1;
16 typedef DefaultPolicy2 P2;
17 typedef DefaultPolicy3 P3;
18 typedef DefaultPolicy4 P4;
19 };
20
21 //這裡之是以給出中間類DefaultPolicyArgs,同時又讓該類以虛拟繼承的方式繼承
22 //DefaultPolicies,一是為了避免後面在多重繼承同一基類時而導緻的二義性,同時
23 //也是為了友善後面其他類的繼承。
24 class DefaultPolicyArgs : virtual public DefaultPolicies {
25 };
26
27 //這裡之是以有第二個常量模闆參數,是為了避免重複繼承相同的基類。
28 template<typename Base, int D>
29 class Discriminator : public Base {
30 };
31
32 //在這裡,如果沒有Discriminator的常量模闆參數,将極有可能導緻繼承同一個基類。
33 template<typename Setter1, typename Setter2,
34 typename Setter3, typename Setter4>
35 class PolicySelector : public Discriminator<Setter1,1>,public Discriminator<Setter2,2>,
36 public Discriminator<Setter3,3>, public Discriminator<Setter4,4> {
37 };
38
39 template<typename PolicySetter1 = DefaultPolicyArgs,
40 typename PolicySetter2 = DefaultPolicyArgs,
41 typename PolicySetter3 = DefaultPolicyArgs,
42 typename PolicySetter4 = DefaultPolicyArgs>
43 class BreadSlicer {
44 public:
45 //在該類後面的實作中,不要直接使用模闆參數,而是要使用Policies::P1, P2, P3, P4等。
46 typedef PolicySelector<PolicySetter1,PolicySetter2,PolicySetter3,PolicySetter4> Policies;
47 void DoTest() {
48 printf("Policies::P1 is %s\n",typeid(Policies::P1).name());
49 printf("Policies::P2 is %s\n",typeid(Policies::P2).name());
50 printf("Policies::P3 is %s\n",typeid(Policies::P3).name());
51 printf("Policies::P4 is %s\n",typeid(Policies::P4).name());
52 }
53 };
54
55 template<typename Policy>
56 class Policy1_is : virtual public DefaultPolicies {
57 public:
58 typedef Policy P1; //改寫DefaultPolicies中的基于P1的typedef。
59 };
60
61 template<typename Policy>
62 class Policy2_is : virtual public DefaultPolicies {
63 public:
64 typedef Policy P2; //改寫DefaultPolicies中的基于P2的typedef。
65 };
66
67 template<typename Policy>
68 class Policy3_is : virtual public DefaultPolicies {
69 public:
70 typedef Policy P3; //改寫DefaultPolicies中的基于P3的typedef。
71 };
72
73 template<typename Policy>
74 class Policy4_is : virtual public DefaultPolicies {
75 public:
76 typedef Policy P4; //改寫DefaultPolicies中的基于P4的typedef。
77 };
78
79 class CustomPolicy {};
80
81 int main() {
82 BreadSlicer<Policy3_is<CustomPolicy> > bc;
83 bc.DoTest();
84 getch();
85 return 0;
86 }
87 //Policies::P1 is class DefaultPolicy1
88 //Policies::P2 is class DefaultPolicy2
89 //Policies::P3 is class CustomPolicy
90 //Policies::P4 is class DefaultPolicy4
在上面的例子中一個非常重要的特點是,所有的模闆實參都是DefaultPolicies的派生類。在聲明BreadSlicer對象時,不同的派生類将覆寫不同的DefaultPolicies中的typedef。
二、遞歸模闆模式:
這是一種通用的模闆設計模式,即派生類将本身作為模闆參數傳遞給基類,如:
template<typename DerivedT>
class Base {
... ...
};
class MyDerived : public Base<MyDerived> {
... ...
};
基于這種模式,有一個非常著名的用例,即[MeyersCounting],是《Effective C++》的作者Scott Meyers所設計的。通過繼承以下代碼中的基類,所有的派生類便可實作類執行個體計數的功能。在下面的基類中,将包含一個表示對象計數的靜态成員,同時還會在基類構造的時候遞增該值,并在析構的時候遞減該值,見如下代碼示例:
文章來自http://absoso.com/zhuanjiabaoliao/2012090934.html
1 #include <stdio.h>
2 #include <conio.h>
3
4 template<typename CountedType>
5 class ObjectCounter {
6 private:
7 static size_t count;
8
9 protected:
10 ObjectCounter() {
11 ++ObjectCounter<CountedType>::count;
12 }
13 ObjectCounter(ObjectCounter<CountedType> const&) {
14 ++ObjectCounter<CountedType>::count;
15 }
16 ~ObjectCounter() {
17 --ObjectCounter<CountedType>::count;
18 }
19
20 public:
21 static size_t liveCount() {
22 return ObjectCounter<CountedType>::count;
23 }
24 };
25
26 template<typename CountedType>
27 size_t ObjectCounter<CountedType>::count = 0;
28
29 //C++編譯器會根據模闆參數的不同執行個體化不同類型的類對象,是以模闆參數不同,所使用的靜态成員也是不同的。
30 class MyClass : public ObjectCounter<MyClass> {
31 };
32
33 int main() {
34 MyClass mc1;
35 printf("The count of MyClass is %d\n",MyClass::liveCount());
36 {
37 MyClass mc2;
38 printf("The count of MyClass is %d\n",MyClass::liveCount());
39 }
40 printf("The count of MyClass is %d\n",MyClass::liveCount());
41 getch();
42 return 0;
43 }
44 //The count of MyClass is 1
45 //The count of MyClass is 2
46 //The count of MyClass is 1