《C++設計新思維》讀書筆記(二)
1.5 Policies和Policy Classes
舉例,定義一個policy生成對象:Creator policy 提供一個Create函數,返回一個指向新生T類型對象的指針。
我們有三種做法:
1 template<class T>
2 struct OpNewCreator{
3 static T* Create(){
4 return New T;
5 }
6 };
7 template <class T>
8 struct MallocCreator{
9 static T* Create(){
10 void* buf = std::malloc(sizeof(T));
11 if(!buf) return 0;
12 return new(buf) T; //定位new表達式,見《C++ primer》8.4.5, cuigang
13 }
14 };
15 template <class T>
16 struct PrototypeCreator{
17 PrototypeCreator(T* pObj =0):pPrototype_(pObj){}
18 T* Create(){
19 return pPrototype_? pPrototype_->Clone():0;
20 }
21 T* GetPrototype(){ return pPrototype_;}
22 void SetPrototype(T* pObj){pPrototype_ = pObj;}
23 private:
24 T* pPrototype_;
25 };
26
這些實作出來的policy稱為policy classes,這個東西并不意圖被單獨使用,它們主要用于繼承或被內含于其它classes。
一個類以復合或繼承的方式使用先前定義的三個classes之一,例如
1 //Library code
2 template <class CreationPolicy>
3 class WidgetManager : public CreationPolicy{};
如果class采用一個或多個policies,我們稱為hosts或host classes。
客戶端如此實例化:
1 //Application code
2 typedef WidgetManager< OpNewCreator<widget> > MywidgetMgr;
讓我們分析整個來龍去脈。無論何時,當一個MywidgetMgr對象需要產生一個widget對象時,它便調用它的policy子對象OpNewCreator<widget>所提供的Createv()。選擇“生成策略”(Creation policy)是WidgetManager使用者的權利。藉由這樣的設計,可以讓WidgetManager使用者自行裝配他所需要的機能。
這便是Policy-based class的設計主旨。
==============================
1 template <class T>
2 void* buf = std::malloc(sizeof(T));
3 void* buf = (void*)new T;
當T為基類,具有派生類時,兩者申請的內存大小是不一致的,sizeof(T)不包括 virtual table 的大小。
——鐘遙
//////////////////////////////
鐘遙過慮了,以下代碼
1 struct base{
2 int x;
3 base(){
4 std::cout<< "create a base."<<std::endl;
5 }
6 virtual void foo(){
7 std::cout<<"call base"<<std::endl;
8 };
9 };
10 struct test : public base{
11 int y;
12 test(){
13 std::cout<< "create a test."<<std::endl;
14 }
15 virtual void foo(){
16 std::cout<<"call test."<<std::endl;
17 }
18 void foo2(){};
19 };
20 /////////////////////////
21 int a = sizeof(test);
22 int b = sizeof(base);
23 std::cout<<"sizeof(test)="<< a << ", "<<"sizeof(base)=" << b << endl;
24 base* pa = new base;
25 base* pb = new test;
26 std::cout<<"---------"<<endl;
27 base* ppa = (base*)malloc(sizeof(base));
28 base* ppb = (base*)malloc(sizeof(test));
29 std::cout<<"---------"<<endl;
30 new(ppa) base;
31 new(ppb) test;
32 pa->foo();
33 pb->foo();
34 ppa->foo();
35 ppb->foo();
輸出結果:
1 sizeof(test)=12, sizeof(base)=8
2 create a base.
3 create a base.
4 create a test.
5 ---------
6 ---------
7 create a base.
8 create a base.
9 create a test.
10 call base
11 call test.
12 call base
13 call test.