Step By Step(C++模板和继承)

[来源] 达内    [编辑] 达内   [时间]2012-09-13

有些高级脚本语言,如Perl、PL/SQL等,他们的函数参数在调用时都支持命名参数,既在调用时可以不按照顺序传递参数,而是p可以按照参数的名字传递。

一、命名模板参数:

    有些高级脚本语言,如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>。下面将给出一些具体的实现,请务必留意代码中的关键性注释:

< div style="background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 12px; border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; max-width: 900px; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 18px; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " class="cnblogs_code">
 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
< p style="margin: 5px auto; text-indent: 0px; color: rgb(0, 0, 0); font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 18px; orphans: 2; text-align: -webkit-auto; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); ">     在上面的例子中一个非常重要的特点是,所有的模板实参都是DefaultPolicies的派生类。在声明BreadSlicer对象时,不同的派生类将覆盖不同的DefaultPolicies中的typedef。
    
二、递归模板模式:

    这是一种通用的模板设计模式,即派生类将本身作为模板参数传递给基类,如:
    template<typename DerivedT>
    class Base {
        ... ...
    };
    class MyDerived : public Base<MyDerived> {
        ... ...
    };
    基于这种模式,有一个非常著名的用例,即[MeyersCounting],是《Effective C++》的作者Scott Meyers所设计的。通过继承以下代码中的基类,所有的派生类便可实现类实例计数的功能。在下面的基类中,将包含一个表示对象计数的静态成员,同时还会在基类构造的时候递增该值,并在析构的时候递减该值,见如下代码示例:

< div style="background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 12px; border: 1px solid rgb(204, 204, 204); padding: 5px; overflow: auto; margin: 5px 0px; max-width: 900px; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 18px; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " class="cnblogs_code">
 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>ount; 
12         } 


13         ObjectCounter(ObjectCounter<CountedType> const&) { 
14             ++ObjectCounter<CountedType>ount; 
15         } 


16         ~ObjectCounter() { 17
             --ObjectCounter<CountedType>ount; 18
         } 19
     
20     public
: 21
         static

 size_t liveCount() { 22
             return ObjectCounter<CountedType>ount; 


23         } 24
     }; 25
     
26     template<typename CountedType>
27     size_t ObjectCounter<CountedType>ount = 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

资源下载