roger(
1.當作類物件的「共享控制代碼」來使用
2.在類內部提供資源管理服務 —— 「為類提供資源的共享拷貝語義
(或稱為淺拷貝
shadow copy
),並在正確的時間**資源」
上述的兩種方式一種是在類外部使用,一種是在類內部使用,然而這兩種方式並不是非此即彼的關係,很多情況下我們都可以選擇任意一種,選擇其中一種理由通常是遵循「更容易被使用,更難以被誤用」的原則。
當作類物件的「共享控制代碼」來使用
在這種使用方式下,結合create method模式使用會取得更好的效果
(關於create method
模式,更多資訊請看「模式與重構一書」)。
以下是乙個使用場景,我們有乙個類,類封裝了乙個底層資源的控制代碼和跟控制代碼相關的所有api呼叫
(控制代碼和
api呼叫來自作業系統或者其它的
c函式庫)。
控制代碼在不再被使用的時候需要被釋放
(析構函式是最適合做這件事的,不是嗎?);
控制代碼的拷貝可能是一種危險的行為
(通常控制代碼的實現都是所謂的
opaque pointer
不透明指標,也是說該指標實際是指向一塊
api操作的資料結構,只是該資料結構是不對外公開的,這也是所謂的c-
oo風格),因為有可能導致懸掛控制代碼
(其實也是懸掛指標)或者由於釋放的責任模糊而導致重複釋放。
所以,我們用類封裝底層資源控制代碼,但不為該類提供拷貝行為,而是通過外裹的share_ptr來提供共享拷貝語義。
下面是乙個實際例子,來自我自己封裝lcms庫profile控制代碼的乙個類
(lcms
是乙個開源用於色彩管理的
c函式庫,也是乙個輕量級可用於學習
c-oo
程式設計的不錯選擇),cmshprofile是lcms的profile
(特性檔案)資源控制代碼。
kprofile.h
#pragma
once
#include
"kprofileshptr.h
"#include
<
lcms
/lcms.h
>
namespace
milk
/** print out
*/ostream
&print(ostream&)
const;/*
* basic information related function.
*/string
getproductname()
const
;string
getproductdescription()
const
;string
getproductinformation()
const
;string
getmanufacturer()
const
;string
getmodel()
const
;string
const
;uint32 getprofileversion()
const
;string
getprofileversionstring()
const
;private
:kprofile();
kprofile(cmshprofile);
kprofile(
const
char*,
const
char*);
kprofile(
void
*, uint32);
cmshprofile handle_;};}
1.kprofile 封裝了cmshprofile(
handle_
)控制代碼,和許多相關的lcms api呼叫 2.
從boost庫的noncopyable獲得禁止拷貝的行為(拷貝建構函式和賦值操作符)
3.kprofile不提供public的建構函式,而是提供一系列的create methods,所有的create methods都返回kprofileshptr(
typedef boost::shared_ptrkprofileshptr)4.
gethandle函式會返回內部profile控制代碼(資源封裝類應該允許返回內部的控制代碼或者指標,參看
effective c++
第三版)
kprofileshptr.h
#pragma
once
namespace
milk
1.另外提供乙個kprofileshptr.h而不把typedef置於kprofile.h內的原因是為了提供kprofileshptr的前置宣告
(類似c++標準庫
iosfwd
的做法),就是說當其它類的介面需要使用到kprofileshptr的時候,它不必在標頭檔案中包括kprofile.h,而只需要包括kprofileshptr.h即可。(當然在所有的地方都寫boost::shared_ptr可以免除這種麻煩,看個人喜好)
kprofile.cpp
#include
"kprofile.h
"#include
"kcm***ception.h
"namespace
milk
kprofile::kprofile(cmshprofile handle)
: handle_(handle)
kprofile::
~kprofile(
void
)kprofileshptr
kprofile::createfromhandle(cmshprofile handle)}
1.在析構函式中會釋放profile控制代碼
2.由於kprofile沒有提供拷貝行為,所以析構函式不會擔心會多次釋放同一控制代碼,當然如果釋放發生在類外部,這不是類kprofile可以控制的
TabWidget TabHost的兩種使用方法
android tabwidget tabhost有兩種使用方法 第一種 使用系統自帶寫好的tabhost 及繼承自tabactivity類 具體 如下 package com.aina.android import android.content.dialoginte ce import andr...
angularjs的 filter的兩種使用
我們可以直接在 中使用filter,跟在表示式後面用 分割,語法如下 filter可以接收引數,引數用 進行分割,如下 除了對 中的資料進行格式化,我們還可以在指令中使用filter,例如先對陣列array進行過濾處理,然後再迴圈輸出 我們的js 中也可以使用過濾器,方式就是我們熟悉的依賴注入,例如...
XML的兩種常見格式
寫了好長時間感覺sax解析也不難理解,主要是xml文件的格式我們不熟悉,熟悉了xml文件的格式,再來看sax解析就好多了 所以寫了這篇關於xml文件常見的兩種格式的詳細解讀 先來模擬一下兩種格式 xml第一種形式 此時我們需要解析的是元素 元素屬性 下面是nsparser的幾個 方法,給出列印結果,...