柴郡貓技術 C 中的PIMPL設計模式

2021-09-13 14:57:52 字數 4616 閱讀 2662

c++ 中的「柴郡貓技術」(cheshire cat idiom),又稱為 pimpl(pointer to implementation) ,opaque pointer 等,是一種在類中只定義介面,而將私有資料成員封裝在另乙個實現類中的慣用法。該方法主要是為了隱藏類的資料以及減輕編譯時的壓力。

「柴郡貓」是什麼鬼?就是下面這貨:

cheshire cat

柴郡貓的能力和 pimpl 的功能相一致,即雖然資料成員「消失」了(被隱藏了),但是我們的「柴郡貓」的笑容還是可以發揮威力。

下面通過例子來介紹一下 pimpl 。

c++ 中我們在標頭檔案中定義類,比如乙個簡單的 student 類由如下方式定義:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

// student.h

class student

;這裡_name_agestudent類的私有資料成員。然而使用該類的客戶往往更關心類的介面(該類能提供哪些服務),我們希望隱藏student類的私有資料成員,這時候就可以利用 pimpl 模式:定義乙個實現類,將student類的資料封裝到這個實現類中,同時在student類中保留乙個指向該實現類的指標變數。用**解釋更清楚:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

// student.h

class student

;1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

// student.cpp

#include "student.h"

#include

#include

using namespace std;

class student::cheshirecat

~cheshirecat() {}

string _name;

int _age;

};student::student() :

_smilecat(

new cheshirecat())

student::~student()

void student::sayhello(std::ostream &out)

string student::getname()

void student::setname(string name)

int student::getage()

void student::setage(int age)

好了,現在student類的介面沒有任何變化,但是標頭檔案中原有的私有資料成員消失了,只留下乙隻微笑的柴郡貓(cheshirecat *_smilecat;)。

使用 pimpl 可以幫助我們節省程式編譯的時間。考慮下面這個類:

1

2

3

4

5

6

7

8

9

10

11

12

// a.h

#include "bigclass.h"

#include "verybigclass"

class a

;我們知道c++中有標頭檔案(.h)和實現檔案(.cpp),一旦標頭檔案發生變化,不管多小的變化,所有引用它的檔案都必須重新編譯。對於乙個很大的專案,c++一次編譯可能就會耗費大量的時間,如果**需要頻繁改動,那真的是不能忍。這裡如果我們把bigclass big;verybigclass verybig;利用 pimpl 封裝到乙個實現類中,就可以減少 a.h 的編譯依賴,起到減少編譯時間的效果:

1

2

3

4

5

6

7

8

9

10

11

// a.h

class a

;使用 pimpl 需要在堆空間上分配和釋放記憶體,記憶體開銷增加,同時也需要更多的間接指標跳轉,因此有一些***。

雖然如此,pimpl 仍然是一種實現資料隱藏、減少編譯時間的有效方法。除非會引起顯著的程式效能下降,推薦使用 pimpl 進行設計。

現代 c++ 中不提倡使用 owning raw pointers 和delete,我們可以用智慧型指標實現 pimpl。

1

2

3

4

5

6

7

8

9

10

// myclass.h

class myclass

;1

2

3

4

5

6

7

8

9

10

11

// myclass.cpp

class myclass::aimpl

;myclass::myclass() : _pimpl(

new aimpl())

posted @

2016-12-16 10:07

心靈捕手 閱讀(

...)  

編輯收藏

c 中log的設計

兵馬未動,糧草先行 在進行工程構建前,最先需要考慮的就是日誌系統,用於程式除錯。目前,已經有很多開源庫可供使用 1 其中比較出名的是glog 2 谷歌出品的。我偶爾也寫點程式,之前看到caffee中的日誌模組,我就把它拿了出來 3 以備使用。我最近在寫程式,恰好就把摘出來的日誌模組使用上了。但是我在...

C 中的config設計

配置檔案讀寫類,它要有以下這些方法 1.支援讀入乙個指定配置檔案的能力 2.支援隨時加入乙個配置項的能力 3.足夠強大,能夠寫入各種資料結構的配置資訊 c 裡,我們要儲存這樣的資料就使用 std map 即可。也就是說,我們的 config 類中,需要有乙個最基本最基本的儲存配置檔案鍵值對資訊的 s...

深度學習中的網路設計技術 二 正則化技術

1.什麼是過擬合?什麼是欠擬合?過擬合其實就是在訓練樣本內能夠很好的擬合資料,而在訓練樣本外 沒有參與訓練的樣本 擬合效果很差,這樣的現象就是過擬合。如果你在訓練網路的過程中發現,模型準確率很高,但是在測試的時候發現準確率很低,那麼有可能就是發生了過擬合現象。也就是數過擬合沒有好的泛化能力。泛化 指...