C 中的控制代碼類(智慧型指標)

2022-08-05 09:30:15 字數 3393 閱讀 5929

最近工作中用到了控制代碼類,特意了解了一下,後來發現所謂的控制代碼其實和智慧型指標就是一回事。為了能夠更好的理解控制代碼類,建議大家先了解c++中類、類的繼承、多型等概念,不然很容易懵。

控制代碼(handler)之所以翻譯成柄,就是用乙個類來撬動很多類。類似於從一大堆數中,只要拿著乙個數(基類),後面跟著很多數(繼承類)也都順帶被拿起來了。

控制代碼的實現主要實現了三個作用:

先來看乙個例子,此處參考神奇愛哥的博文。

#include#include

using

namespace

std;

class

a ~a(){}

virtual

void

func()

};class b: public

a ~b(){}

void

func()

};int

main()

最後的輸出是:

因為物件b的拷貝在vector中時被強制轉換成基類了。

要在乙個容器中放基類及其繼承類的時候總會遇到這個問題,因為vector的型別只能被宣告為某乙個類(假設為基類),那麼繼承類的資訊就丟失了。

首先可以想到用指標來實現多型,例如vector。但是這樣必須要程式設計師來接管記憶體。

b *b = new b;

vec.push_back(b);

這時加入vec的生命週期結束了,vec不會主動釋放b所占用的記憶體,如果不手動deleteb,那麼就會造成記憶體洩漏。

而控制代碼類可以解決這個問題。

#include#include

using

namespace

std;

class

a ~a(){}

virtual

void func() const

virtual a* clone() const

//為了實現控制代碼類新增的函式

};class b: public

a ~b(){}

void func() const

virtual b* clone() const

//為了實現控制代碼類新增的函式

};class

sample

sample(

const a& a):p(a.clone()) //

引用構造

sample(const sample& i):p(i.p),use(i.use) //

引用構造

~sample()

sample& operator=(const sample &i)

const a* operator->() const

const a& operator*() const

private

: a*p;

size_t use;

void decr_use()

};int

main()

此時執行結果為:

因此控制代碼類方便得實現了多型,並且和智慧型指標一樣可以自動管理記憶體。

上面的**需要注意為什麼轉殖函式裡要用

virtual a* clone() const

而不是直接virtual a* clones() const(return this;}

這是為了避免這樣一種情況:

b b;

sample sam(b);

vec.push_back(sam);

當b的生命週期結束,而vec的生命週期未結束時,呼叫(*iter)->func就會出錯。

從上面的例子中可以看出,控制代碼類sample的實現和它所管理的類a的實現時完全獨立的。因此即使更改了a的功能,控制代碼類也依然可以保持不變。

在使用控制代碼類需要特別注意的一點是,操作控制代碼類時本質就是在操作指標,有時解引用了非const的函式可能就會直接改變其真正指向的物件。

來看乙個例子。

#include#include

using

namespace

std;

class

a ~a(){}

virtual

void func() const

virtual a* clone() const

//為了實現控制代碼類新增的函式

void setnum(int n) //

增加了乙個設定num屬性的函式

int getnum() const

private

:

intnuma;

};class b: public

a ~b(){}

void func() const

virtual b* clone() const

//為了實現控制代碼類新增的函式

void setnum(int n) //

增加了乙個設定num屬性的函式

int getnum() const

private

:

intnumb;

};class

sample

sample(

const a& a):p(a.clone()) //

引用構造

sample(const sample& i):p(i.p),use(i.use) //

引用構造

~sample()

sample& operator=(const sample &i)

a* operator->() const

a& operator*() const

private

: a*p;

size_t use;

void decr_use()

};void

changea(sample sam)

intmain()

在呼叫changea時,注意並非引用呼叫,而是直接把sample物件傳遞進來。

輸出結果為:

可以看出,changea的形參並沒有顯示指定是指標,也不是引用,但是卻真實得改變了s1指向物件的值。

由於s1(a)時執行了建構函式構造了新的物件,因此s1與a其實無關,所以a的值不變。

所以在使用控制代碼類時需要牢記自己操作的是指標,雖然看起來像物件,但是本質是指標。 

參考:

C 控制代碼類(智慧型指標)小結

控制代碼類作用主要有兩個 控制代碼類儲存和管理基類指標,指標既可以指向基類型別物件又可以指向派生型別物件。使用者通過控制代碼類訪問繼承層次的操作,使用者 可以獲得動態行為 同時能夠確保自動正確的銷毀動態分配的物件,防止記憶體洩露。c primer 15.7節中用購物籃的例子說明 了c 不能通過物件 ...

智慧型指標類模板(中) Qt中的智慧型指標

qt中的智慧型指標 qpointer 當其指向的物件被銷毀時,它會被自動置空 析構時不會自動銷毀所指向的物件 qsharedpointer 引用計數型智慧型指標 可以被自由的拷貝和賦值 當引用計數為0時才刪除指向的物件 include include using namespace std clas...

智慧型指標類模板(中) Qt中的智慧型指標

qt中的智慧型指標 qpointer 當其指向的物件被銷毀時,它會被自動置空 析構時不會自動銷毀所指向的物件 qsharedpointer 引用計數型智慧型指標 可以被自由的拷貝和賦值 當引用計數為0時才刪除指向的物件 include include using namespace std clas...