C 泛型程式設計 基於策略 Policy 的類設計

2021-06-09 00:25:45 字數 4150 閱讀 6385

基於策略(policy)的類設計是將templates和多重繼承組合起來,這樣可以產生程式庫中的「設計元素」。policies由templates和多重繼承組成。乙個class如果使用了policies,就稱其為host class,那是乙個擁有多個template引數的class template,每乙個引數代表乙個policy.host class所有的機能都來自policies,運作起來就像是乙個聚合了數個policies的容器。

1.什麼是policy?

它是用來定義乙個class或class template的介面,該介面由下面專案的之一或 全部組成:內隱型別定義(如typedef int * pointer)、成員函式和成員變數。policies有點類似設計模式中的strategy,只不過policies更注重編譯器。而strategy更注重執行期。

例子1:定義乙個ploicy 用來產生物件,creator policy是乙個帶有型別為t的class template,它必須提供乙個名為create()的函式給外界使用,此函式不接受引數,返回乙個指向t的指標。下面是三種產生物件的方法即policy:

policy 1:

templatestruct opnewcreator

};policy 2:

templatestruct malloccreator

};policy 3:

templatestruct prototypecreator

t * create()

t *getprototype()

void setprototype(t* pobj)

private:

t * pprototype_;

};

上面三個policy稱為policy classes.這些東西並不是用來單獨使用,主要是用於繼承或被內含於其他的類。

creator policy並沒有規定create()必須是static 還是virtual,只要求class必須定義乙個create().你可以定義多個policy class,但是必須遵循統一的介面。

2.利用前面的creator policy,怎麼樣設計乙個類?

我們可以用復合或繼承的方式使用前面定義的三個類之一。

例如: 

templateclass widgetmanager:public creationpolicy

;

如果乙個類採用了乙個或多個policy class,就稱其為host或host classes.上面定義的widgetmanager採用了乙個policy,稱其為host class.hosts主要負責把上面定義的policies的結構和行為組成乙個風複雜的結構和行為。

使用者可以將widgetmanager例項化,傳進乙個使用者指定的policy,如下:

typedef widgetmanager> mywidgetptr;

當乙個mywidgetptr需要產生乙個widget物件時,它就呼叫它的policy子物件opnewcreator所提供的create()函式。widgetmanager是用來選擇生成策略(creation policy)的(基於policy設計類的宗旨)。

3.怎麼樣為host class 中的policy classes的引數設定預設值?

在前面可以看到,policy 類的template引數是非常累贅的。使用者每次都需要向policy 類(如opnewcreator)傳遞乙個template引數,表示需要建立的物件。如果使用者操作的物件固定,就不需要每次都傳遞這個引數,可以採用預設的物件來例項化。

a.採用template template引數來設定預設值

template class creationpolicy>

class widgetmanager:public creationpolicy

//created 是creationpolicy的引數。creationpolicy 是widgetmanager的引數。上面的widget已經寫入程式庫,使用時不需要再傳一次引數給policy.可以採用如下方式使用:

typedef widgetmanagermywidgetmgr;

如果使用者想要用widgetmanger的相同策略產生乙個gadget物件,如下:

templateclass creationpolicy>

class widgetmanager:public creationpolicy

};

注:為常用的policy提供預設的引數:

template class creationpolicy=opnewcreator>

class widgetmanager...;

policies有豐富的型別資訊及靜態連線等特性,在編譯期才把host class和policies結合在一起,所以是建立「設計元素」時的本質性東西。

b.利用template成員函式來定義policy class。

我們可以重新定義之前的policy為非template class,該函式內部定義乙個template函式,如下:

struct opnewcreator

};

這樣定義的policy,對舊的編譯器比較相容。這樣的policy難以討論,定義和運用。

4.policy classes的析構函式

大部分情況下,host class會以public方式繼承某些policies,所以呼叫者可以將乙個host class自動轉為乙個policy class,並delete 該指標。除非為policy class定義虛析構函式,否則delete乙個執行policy class的指標,會產生不可預期的結果。然而如果為policy定乙個虛析構函式,會影響policy的靜態鏈結特性,也會影響執行效率。

許多policies並沒有資料成員,只純粹提供乙個介面。虛函式的加入會為物件的大學帶來額外開銷,所以虛函式應該盡量避免。

乙個解決辦法是host class 派生policy class時候,採用protected或private繼承。但這樣會失去豐富的policies特性。

另乙個有效的解法是定義乙個protected的析構函式。由於是protected,只有派生而得的類才可以摧毀這個policy物件。這樣外界就不可能delete乙個指向policy class的指標。由於析構函式不是虛函式,不會帶來大小或速度上的額外開銷。

5.通過不完全具現化獲取選擇機能

c++的有趣特性,造就了policies的豐富特性。如果class template有乙個成員函式沒有用到,它就不會被編譯器具體實現出來。編譯器不會理會,甚至不進行語法檢驗。這樣就可以讓host class有機會並使用policy class的可選特性。如下:

templateclass creationpolicy>

class widgetmanage:public creationpolicy

};

如果你採用乙個定義了setprototype()函式的creator policy來例項化widgetmanager,就可以使用switchprototype()函式。若採用不支援setprototype()函式的creator policy來例項化widgetmanager,就會引數編譯錯誤。如果你採用乙個不支援setprototype()函式的creator policy來例項化widgetmanager,如果使用在沒有呼叫switchprototype(),程式是合法的。

6.用policy class定製結構

templates的限制之一是你無法定製class的結構,只能定製其行為。然而基於policy 類的設計支援結構方面的定製。

一般像如下定義:

templateclass smartptrstorage

void setpointer(pointertype ptr)

private:

pointertype pointee_;

};

複製搜尋 複製

搜尋

c 泛型程式設計

對於兩個不同的概念a和b,如果概念a所需求的所有功能也是概念b所需求的功能,那麼就說概念b是概念a的子概念。例如 標準模板庫 standard template library,簡稱stl 提供了一些非常常用的資料結構和演算法 將函式物件作為演算法的引數而不是將函式所執行的運算作為演算法的一部分。使...

C 泛型程式設計

1.模板介紹 泛型程式設計 指的是直接應用 使用模板編寫好的函式模板或類模板庫程式 進行程式設計。在具體使用時,程式設計師只需向使用的庫函式或類模板提供型別或值即可。模板是泛型程式設計的基礎。比如使用標準模板庫中的容器 迭代器進行程式設計,就是泛型程式設計。模板函式 模板函式 強調的是函式,函式使用...

C語言泛型程式設計 泛型氣泡排序

在實際程式設計中,常常會需要一些方法 函式 比如排序,它們具體實現基本一致,僅僅只有引數型別不同,那麼可不可以有一種通用的函式,不管是什麼型別的引數都可以通用呢?泛型程式設計 泛型即是指具有在多種資料型別上皆可操作的含義,與模板有些相似。利用泛型程式設計,我們可以寫一些通用的函式,以減少 量,實現 ...