在**類的幫助下,我們已經可以實現在乙個容器裡儲存乙個類層次裡所有型別的物件,但是**有乙個很明顯的缺點,就是需要複製物件,當乙個物件非常大或者是一種不能輕易複製的資源的時候,這個實現遇到了很大的困難,於是我們有了控制代碼(handle)類這個技術。
我們有這麼乙個類
class point
point(
int x,
int y)
:x_cdt(x)
,y_cdt(y)
int get_x(
)int get_y(
)point& set_x(
int x)
//返回值是point&是為了實現這樣的表達
point& set_y(
int y)
private
:int x_cdt,y_cdt;};
這個類有一切他應該有的成員函式,然後我們希望有這麼乙個handle能夠替代實現他的所有功能,而又保證不需要複製這個物件,我們能想到的第乙個方法當然是得到這個物件的指標但是這樣我們就又把記憶體的分配暴露到了使用者面前,可以隨意的得到底層的指標。這個handle第一次是寫成這樣的:
class handle
我們暫時沒有把set_x()這樣的成員先假如到這裡,為了簡便。當我們寫完之後,我們又遇到了時刻困擾我們的問題,就是物件的刪除,既然我們允許把乙個物件繫結到多個handle上,當其中的乙個handle刪除的時候,這個物件會怎麼樣呢?這個問題是要解決的。這裡,我們呢引入了引用計數的概念,很顯然,我們不能把這個引用計數放到我們的handle類中,因為一旦我們這麼做了,當我們用乙個handle繫結到乙個物件的時候,他必須知道其他所有繫結到這個物件的handle的引用計數,然後更新這個計數,這非常困難。那麼如果我們把這個引用計數放到物件本身呢?稍微思考一下就知道也是不合理的,這樣做意味著我們每次都要改寫物件。所以,綜上考慮,我們決定寫乙個新的類來存放這個引用計數,這個類是完全為了技術的實現設計的,所以我們把他的所有成員設定成private,而讓handle成為他的友元類,具體是這樣的:
class count_point
;
有了這個引用計數,我們就可以讓我們之前的乙個小憂慮變得合理點,就是我們在handle中有乙個point* operator-
>()
;現在我們這樣改寫這個handle類:
class handle
;
好了,至此,框架已經行程,我們來實現控制代碼。
class count_point
count_point(
int x,
int y)
:p(x,y)
,count
(1)count_point(
const point&h)
:p(h)
,count
(1)}
;
然後是handle類:
class handle
handle(
int x,
int y)
:ptr(
new count_point(x,y)
)handle(
const point&h)
:ptr(
new count_point(h)
)handle(
const handle&h)
:ptr(h.ptr)
handle&
operator=(
const handle&h)
~handle(
)private
:count_point* ptr;};
最後,我們還有乙個小任務,就是實現handle中的set_x()和set_y()成員,注意當初我們為了看上去簡便暫時沒有把他們新增到handle中,事實上他們是應該被包含的,我們來定義乙個
handle:
:set_x(
int x)
不得不提醒,這裡涉及到指標語義和值語義的問題,我們這樣做,是選擇了指標語義,這樣做的後果就是,你改動乙個handle繫結的物件將使所有與這個物件繫結的handle發生一樣的變化,這樣可以避免複製。
二:在我的前一篇博文裡,我們討論了有關控制代碼類的實現,這個控制代碼類有乙個明顯的缺陷,那就是必須知道你要**的那個類的具體型別,如果是乙個繼承類的話,我們之前的實現就出問題了。這個問題就是
class count_point
;
現在如果我們把引用計數從count_point類中分離出來,也就是我們這樣寫handle類
class handle
使用了這個point的指標後我們就可以把這個handle繫結到不管是乙個基類還是他的派生類,這是動態繫結的優點。這裡我們發現捨去了之前我們寫的count_point類,看上去簡潔了很多,以後我們會回頭來寫乙個輔助類。好了,現在要做的就是實現handle類
handle:
:handle(
):ptr(
new point)
,u(new
int(1)
)handle:
:handle(
int x,
int y)
:ptr(
new point(x,y)
),u(
newint
(1))
handle:
:handle(
const point&h)
:ptr(
new point(h)
),u(
)handle:
:handle(
const handle&h)
:ptr(h.p)
,u(h.u)
handle:
:handle&
operator=(
const handle&h)
u = h.u;
ptr = h.ptr;
return
*this;}
現在我們希望最好我們能把引用計數也抽象一下,應該怎麼抽象呢?最好的就是用類類實現,把int*這個計數放到乙個類裡,這個類具有必要的初始化函式,拷貝建構函式,賦值操作符,析構函式,於是我們構造了這樣的乙個類
class usecount
按照慣例,現在我們要做的就是實現它
usecount:
:usecount(
):p(
newint
(1))
usecount:
:usecount(
const usecount& h)
:p(h.p)
usecount:
:~usecount(
)
注意我們沒有實現賦值操作符,等下會解釋為什麼這麼做,現在我們可以改寫handle類了
class handle
按照老習慣,接下來要實現這個類的成員函式
handle:
:handle(
):ptr(
new point)
handle:
:handle(
int x,
int y)
:ptr(
new point(x,y)
)handle:
:handle(
const point&h)
:ptr(
new point(h)
)handle:
:handle(
const handle&
):ptr(h.ptr)
,u(h.u)
handle:
:~handle(
)
恩,是時候交代一下我們為什麼沒有寫operator=函式了,這個函式要做什麼?他要對乙個計數器加一,對另外乙個減一,可能還要刪除乙個計數器,這些操作很可能改變引用計數,所以我們要在usecount類中新增乙個額外的操作,我們命名為reattach,因為我們不定義operator=了,所以他應該在類中成為乙個私有成員,現在看看reattach的實現
bool usecount:
:reattach(
const usecount&h)
p = h.p;
return
false;}
現在我們可以定義handle的operator=了
handle:
:operator=(
const handle& h)
控制代碼的理解
功能上的理解 什麼是 控制代碼 handle handle的本意是把柄,把手的意思。是你與作業系統打交道的東東。舉個通俗的例子,比如你考上了大學,入學後,學校 作業系統 會給你乙個學生證號。注意,這個號碼是學校指定的,你無法自選。有了這個號碼 學生證,假設一證多用 享受學校提供的服務 如你就可以去圖...
MFC 控制代碼的理解
控制代碼只是從英文 handle 翻譯過來的,只問句是什麼意思難以解釋,這個是我從別人的空間收集的資訊,功能上的理解 什麼是 控制代碼 handle handle 的本意是把柄,把手的意思。是你與作業系統打交道的東東。舉個通俗的例子,比如你考上了大學,入學後,學校 作業系統 會給你乙個學生證號。注意...
控制代碼Handler的理解
總的來說,控制代碼可以簡單理解為指標,乙個指向指標的指標。控制代碼是wondows用來標識被應用程式所建立或使用的物件的唯一整數,windows使用各種各樣的控制代碼標識諸如應用程式例項,視窗,控制,位圖 gdi物件等等。windows控制代碼有點象c語言中的檔案控制代碼。由以上的引用可知,控制代碼...