如何設計類,可以使得檔案間的編譯依存關係降至最低

2021-08-19 09:59:59 字數 2547 閱讀 8558

方法一:使用pimpl idiom(pointer to implementation)的類,常被稱為 handle classes.

將類分割為兩個類,乙個只提供介面,另乙個負責實現該介面。分離的關鍵在於以「宣告的依存性」替換「定義的依存性」。

以person類為例,假設負責實現的那個所謂implementation class取名為personimpl, person將定義如下:

#include//標準程式庫使用預編譯標頭檔案。

#include//為了智慧型指標tr1::shared_ptr而含入

class personimpl; //person實現類的前置宣告

class date; //person介面用到的class的前置宣告

class address;

class person

這裡person類中只內含乙個指標成員,指向其實現類。這種設計常被稱為pimpl idiom(指標實現)。

這樣的設計下,person的客戶就完全與date,address以及personimpl分離了。這些類的任何修改都不需要person客戶端重新編譯。

編譯依存性最小化的本質就是:讓標頭檔案能夠自我滿足,萬一做不到,再讓它與其他檔案內的宣告式相依。

真正用的時候,將所有的函式轉交給相應的實現類,並由實現類完成實際工作。

下面是person類的兩個成員函式的實現:

#include "person.h"   //這裡需要包含person class定義式。

#include "personimpl.h" //也必須包含personimpl class定義式。

person::person(const std::string& name, const date& birthday, const address& addr)

:pimpl(new personimpl(name,birthday,addr))

{}std::string person::name() const

在上方成員函式實現中,person建構函式以new呼叫personimpl建構函式,

在person::name()函式內呼叫personimpl::name。這種設計方法就將類的宣告和實現相分離,從而最大化的減小了編譯依存關係。

對於handle classess這種方法,成員函式必須通過指標實現取得物件資料。這種形式會為每一次訪問增加一層間接性。

而每乙個物件消耗的記憶體數量必須增加實現指標personimpl的大小。並且,這個實現指標personimpl必須在handle classe建構函式內初始化,並指向乙個動態分配得來的實現物件。所以這種操作方法要將蒙受因動態記憶體分配而帶來的額外開銷以及bad_alloc異常(記憶體不足)的可能性。

方法二:令person成為乙個特殊的抽象基類。稱為inte***ce class。

這種類的目的是詳細描述派生類的介面,因此它通常不帶成員變數,也沒有建構函式,只有乙個虛析構函式以及一組純虛函式,用來敘述整個介面。

inte***ce class為這種class建立新物件會採用工廠函式或虛建構函式來實現。這些函式返回指標(通常為智慧型指標),

指向動態分配所得的物件,而該物件支援inte***ce class的介面。這樣的函式往往在inte***ce class內被宣告為static。

實現**如下:

class person;
可以這樣使用它們:、

std::string name;

date dateofbirth;

address address;

//建立乙個物件,支援person介面。

std::tr1::shared_ptrpp(person::create(name,dateofbirth,address));

std::cout當然,支援inte***ce class介面的那個具象類必須被定義出來,而且真正的建構函式必須被呼叫。

假設inte***ce class person有個具象的派生類 realperson,後者提供繼承而來的虛函式的實現:

class realperson: public person

virtual ~person();

virtual std::string name() const = 0;

virtual std::string birthdate() const = 0;

virtual std::string address() const = 0;

private:

std::string thename;

date thebirthdate;

address theaddress;

};

有了realperson之後,寫出person::create的實現**:

person::create(const std::string& name, const date& birthday, const address& addr)

判斷不同設計模式可以使用的關鍵詞

目錄硬編碼 簡單工廠 工廠方法 抽象工廠 建造者原型 單例介面卡 橋接組合 裝飾外觀 享元 職責鏈命令 中介者備忘錄 狀態策略 觀察者重點 命令 模式撤銷 抽象工廠整套?物件類介面卡?明天帶粗鄙 最難的兩套卷 猜20道選擇 40 20min 5簡答 20 20min 2大題 40 20min乙個 最...

C 靜態成員函式可以使用類內的列舉值

看開源 看到類的靜態成員函式可以使用的類內定義的列舉值,似乎與之前學習的時候看到靜態成員函式只能呼叫類內的靜態成員變數。於是做了乙個小實驗,發現真的可以,不知如何解釋。做乙個小的記錄,有時間調查一下,如有大神指教。includeusing namespace std class testclass ...

類定義中可以使用的訪問修飾符組合

類定義中可以使用的訪問修飾符組合 none or internal 類只能在當前工程中訪問 public 類可以在任何地方訪問 abstract or internal abstract 類只能在當前工程中訪問,不能例項化,只能繼承 public abstract 類可以在任何地方訪問,不能例項化,...