控制代碼類(handle class (一)

2021-08-20 13:38:04 字數 2035 閱讀 5414

問題:對於某些類來說,能夠避免複製其物件是很有好處的。因為有可能物件太大,複製起來消耗太大。也有可能每個物件代表一種不能被輕易複製的資源,譬如檔案等等情況。需要有一種方法,讓我們在避免某些缺點(缺乏安全性)的同時能夠獲取指標的某些優點。尤其是在保持多型性的前提下,避免複製物件的代價,因此我們引入控制代碼類來解決這一問題。

以乙個簡單的類作為例子。

關於這個類有必要做三點說明

1.如果使用 point(int x = 0, int y = 0): xval(x), yval(y) {}

來代替上述的兩個建構函式,毫無疑問,可以只需給出x的值便可以構造乙個point物件。而這樣做幾乎可以肯定是錯的。因為乙個點不可能只通過x的值就能確定。

2.過載了x和y成員函式

3.之所以將修改類的物件的成員函式的返回值設定為point&,是因為這樣做便可以連續呼叫該函式以修改物件。如果p是point的乙個物件,那麼便可以使用p.x(2).y(2)的形式修改物件。

接下來我們要考慮的是如何將point物件繫結到控制代碼。

之所以使用控制代碼,原因之一是為了避免不必要的物件複製。也就是說得允許多個控制代碼繫結到單個物件上。將handle類直接繫結到物件p上,那麼handle最好與p的記憶體分配和釋放無關。考慮這樣的情況,handle h(p);如果這樣直接繫結,一旦p被刪除,handle會怎樣呢?顯然,刪除p之後應該使handle無效,那麼handle如何知道p被刪除了呢?或者說,應該同時刪除handle嗎?如果p是乙個區域性變數,那麼p就會被刪除兩次,handle離開時一次,p超出自己作用域一次。

因此,handle應該「控制」它所繫結的到的物件,也就是說handle應該建立和銷毀物件。有兩種可能的選擇:

1.handle h0(123, 456)即把用於建立point的引數傳給這個handle。

2.handle h(p) 即建立自己的point物件並把它賦給乙個handle去進行複製。

簡單的實現:

引用計數型控制代碼

我們必須了解有多少個控制代碼繫結在同一物件上,只有這樣才能確定應當在何時刪除物件。借鑑智慧型指標tr1::shared_ptr的工作機制,我們使用引用計數來達到這個目的。當然這個引用計數不能是控制代碼的一部分。我們必須重新定義乙個類來容納乙個引用計數和乙個point物件。這個類純粹是為了實現而設計的。

到這我們可以回到handle類,來完成成員函式的設計。

接下來我們再考慮最後乙個問題,我們的控制代碼是需要值語義還是指標語義。看下面的例子

handle h(3,4);

handle h2 = h;

h2.x(5);

int n = h.x();

如果希望控制代碼為值語義,則在這個例子中,我們希望n等於3。即繫結到同一物件的控制代碼互不影響。如果採用指標語義則是相反的情況。因此有以下兩種實現方式。

指標語義:

值語義:

需要注意的是,原來handle的引用計數可能不為1,所以需要保證新的handle引用計數為1。這就意味著我們需要在upoint這個類中新增乙個私有成員函式,來設定引用計數。

上面的**運用了一種叫做寫時複製(copy on write),其優點是只有在絕對必要時才進行複製,從而避免了不必要的複製,而且額外開銷也只有一點點。

C 實現控制代碼類(一)

c 學習筆記之實現控制代碼類 寒假看了c 沉思錄和c 程式語言,一直對類的功能分類相關章節記憶猶新,感到這些都是c oop思想的精髓。昨天突然想到為什麼不實踐一下,寫乙個簡單的控制代碼類呢?c 初學者可能不知道控制代碼類為何物。其實說白了,控制代碼類就是為了消除來自同乙個基類的派生類的操作差異性而建...

理解控制代碼類

在 類的幫助下,我們已經可以實現在乙個容器裡儲存乙個類層次裡所有型別的物件,但是 有乙個很明顯的缺點,就是需要複製物件,當乙個物件非常大或者是一種不能輕易複製的資源的時候,這個實現遇到了很大的困難,於是我們有了控制代碼 handle 類這個技術。我們有這麼乙個類 class point point ...

控制代碼類與繼承

前一小節 容器與繼承 提到過 對於容器,如果定義為基類型別,那麼則不能通過容器訪問派生類新增的成員 如果定義為派生類型別,一般不能用它承載基類的物件,即使利用型別轉化強行承載,則基類物件可以訪問沒有意義的派生類成員,這樣做是很危險的。對這個問題的解決辦法,是使用容器儲存基類的指標。在c 中,這類問題...