青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

alex

alex

  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
  7 隨筆 :: 6 文章 :: 7 評論 :: 0 Trackbacks

2007年2月11日 #

今天來講講怎么編寫異常安全的代碼。
程序運行過程中,往往需要對一些流程加入異常處理,來提高程序的robust.比如
通過try catch來捕捉異常
try
{
??? pMemory = new char[MAX_BUF_SIZE];
}
catch(std::bad_alloc& e)
{
??? //error handling,er:do something resource free
}
但在程序代碼段中出現(xiàn)大量的try catch,不僅從美觀,效率和程序輸寫上都是不怎么好。
而另外一種對于異常的處理方法是依賴于c++的ctor/dctor的匹配來做的,就是所謂的
RAII,這個很容易讓人聯(lián)想到std::auto_ptr
std::auto_ptr<int> tmp(new int);
通過new分配的對象會在tmp生命結(jié)束后,釋放相關(guān)的資源,通過這種方式,就能保證在程序異常,或退出時,已分配的對象能正確自動的釋放擁有的資源,而在對象聲明周期內(nèi),可以保證資源的有效性。
這種方式就是今天blog要寫的主要內(nèi)容,我們可以看到std::auto_ptr作用范圍很小,只能對從堆上分配的對象進行管理,假如對文件打開句柄實行RAII,你也許會認(rèn)為再寫個不就是了,但這樣只會造成源代碼里充滿了這些資源管理的類,這導(dǎo)致了一個嚴(yán)重的問題,好的結(jié)構(gòu)在繁瑣的流暢前面變的難堪。
那怎么樣對這個進行泛化,從而能對比如從簡單的指針釋放,文件句柄維護,甚至相關(guān)的成員函數(shù)。我們來看下loki::socpeguard是怎么實現(xiàn)的:
先看下基本的用法
(1)? FILE* hFileOpen = fopen(....);
(2)? LOKI_ON_BLOCK_EXIT(flose,hFileOpen);
line2會在出LOKI_ON_BLOCK_EXIT域或程序異常結(jié)束時被調(diào)用,下面是對類成員的調(diào)用
void CTestObject::Create
{
??? LOKI_ON_BLOCK_EXIT_OBJ(*this,FressResouce);
??? ...
}
同上面差不多,會在這個函數(shù)結(jié)束后或異常結(jié)束后調(diào)用類成員的FreeResource.在正常流程結(jié)束后,可以通過調(diào)用Dismiss來防止對FreeResouce的調(diào)用,即類似數(shù)據(jù)庫操作的commit操作。下面來分析下LOKI的實現(xiàn):
從上面可以看到,RAII的是:
1:構(gòu)造函數(shù)對資源的獲取
2:稀構(gòu)函數(shù)對資源的釋放
先來看下LoKi對上面那2個宏的定義
#define LOKI_ON_BLOCK_EXIT????? Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = Loki::MakeGuard

#define LOKI_ON_BLOCK_EXIT_OBJ? Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = Loki::MakeObjGuard
上面的Loki::ScopeGuard是一個基類的別名
typedef const ScopeGuardImplBase& ScopeGuard;
而LOKI_ANONYMOUS_VARIABLE(scopeGuard)用來我們產(chǎn)生唯一的名字,有時假如需要調(diào)用Dismiss的話,則需要自己去實現(xiàn)宏定義的內(nèi)容,這樣才能通過對象訪問。Loki::MakeGuard或Loki::MakeObjGuard是用來產(chǎn)生對象的實際類型的,下面是一個
Loki::MakeGuard的例子:
template <typename F, typename P1>
inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
{
??? return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
}
可以看到ScopeGuardImpl1<F, P1>是要產(chǎn)生的具體類型,MakeGuard通過函數(shù)參數(shù)的數(shù)目來重載的,而MakeGuard此處的作用是要睡死了...-_-'',作用是利用函數(shù)自動推導(dǎo)出參數(shù)的類型,這樣就免去了指定ScopeGuardImpl1的類型的麻煩,而
ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
簡單的返回對象的一個臨時變量,并assign給一個上面的一個scopeguard的實例,這里依賴一個C++的特性,臨時變量的聲命周期和通過他初始化的引用類型的聲明周期是一致的。

從上面可以看到Loki定義了一個ScopeGuardImplBase的基礎(chǔ)類。這個類定義了一個基本的方法Dismiss,以及相關(guān)的狀態(tài)。下面是loki中這個類的定義
class ScopeGuardImplBase
{
??? ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
?protected:
??? ~ScopeGuardImplBase()
??? {}
??? ScopeGuardImplBase(const ScopeGuardImplBase& other) throw()
??????? : dismissed_(other.dismissed_)
??? {
??????? other.Dismiss();
??? }
??? template <typename J>
??? static void SafeExecute(J& j) throw()
??? {
??????? if (!j.dismissed_)
?????????? try
?????????? {
????????????? j.Execute();
?????????? }
?????????? catch(...)
?????????? {}
???? }
???????
???? mutable bool dismissed_;
public:
???? ScopeGuardImplBase() throw() : dismissed_(false)
???? {}
???? void Dismiss() const throw()
???? {
???????? dismissed_ = true;
????? }
};
可以看到類里面定義了上面所說的一些屬性,其中SafeExecute用來提供子類同一的資源釋放方法,并調(diào)用子類的方法來具體操作,因為相關(guān)的函數(shù),變量都保存在具體的子類,可以看到這個函數(shù)使用了try catch,這里加這個的目的是,因為資源釋放要在子類的稀構(gòu)里被觸發(fā),而調(diào)用具體的方法是外面?zhèn)鬟M來的,所以無法保證一定是異常安全的,而假如在稀構(gòu)里面異常的話,會導(dǎo)致程序的行為無法定義。
下面具體來看下一個子類的實現(xiàn):
template <typename F, typename P1>
class ScopeGuardImpl1 : public ScopeGuardImplBase
{
public:
??? static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
??? {
??????? return ScopeGuardImpl1<F, P1>(fun, p1);
??? }
??? ~ScopeGuardImpl1() throw()
??? {
??????? SafeExecute(*this);
??? }
??? void Execute()
??? {
??????? fun_(p1_);
??? }
protected:
??? ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1)
??? {}
??? F fun_;
??? const P1 p1_;
};
在LoKi里面可以看到很多類似ScopeGuardImpl1的定義,比如ScopeGuardImpl0,
ScopeGuardImpl2,可以發(fā)現(xiàn)最后面的數(shù)字表示具體參數(shù)的數(shù)目。
可以看到上面所說的MakeGuard的定義,以及對基類方法的調(diào)用,可以看到構(gòu)造函數(shù)接收的類型,一個函數(shù)對象,和一些參數(shù)對象,并保存,對于成員函數(shù)的scopeguard,LoKi定義了1些相似的類,主要是增加了對象的引用,還有就是函數(shù)的調(diào)用方式上。
上面可以看到參數(shù)是通過值的方式來保存的而不是通過引用。而且是const屬性的,下面是相關(guān)的分析。
1:通過傳值的方式,從而避免了異常拋出時,可能引用的對象被稀構(gòu)
2:加const屬性,從而保證了在func需要參數(shù)是reference時而保存的參數(shù)確是非const時產(chǎn)生相應(yīng)的編譯錯誤,因為對reference傳人const non-reference形式是錯誤的。
而對于1的方式,存在的一種問題是假如操作的fun需要傳入引用,那傳進去的值就無法在釋放的函數(shù)中被改變,而2是對這種的一種類似契約似的編程,Loki 提供的方法是通過一個中間對象來保存操作參數(shù)的引用,并賦予這個對象自動轉(zhuǎn)換功能。下面是這個類的定義:
template <class T>
class RefToValue
{??
public:
??? RefToValue(T& ref) : ref_(ref)
??? {}
??? RefToValue(const RefToValue& rhs) : ref_(rhs.ref_)
??? {}
??? operator T& () const
??? {
??????? return ref_;
??? }
private:
??? // Disable - not implemented
??? RefToValue();
??? RefToValue& operator=(const RefToValue&);
???????
??? T& ref_;
};
可以很清楚的看到類的實現(xiàn),下面是一個工具類
template <class T>
inline RefToValue<T> ByRef(T& t)
{
???? return RefToValue<T>(t);
}
下面給個具體的例子,假如
template<typename _Ty>
void SAFEDELETE(_Ty*& ptr)
{
?? if (NULL != ptr)
????? delete ptr;
?? ptr = NULL;
}

char* ptr = new char;
?
{
??? LOKI_ON_BLOCK_EXIT(SAFEDELETE<char>,Loki::ByRef(ptr));
}
?
if (NULL == ptr)
? std::cout << "NULL" << std::endl;
基本上就這么多了,sleep去了
??????????????????????????????????????????????????? alex_yuu

posted @ 2007-02-11 15:55 agerlis 閱讀(1409) | 評論 (3)編輯 收藏

聽說過一種時間管理的方法,是用來怎么安排任務(wù)和時間的,下面是大概的概念圖:
?

???????????????????????????????time - task

圖中箭頭指向的方向表示緊迫度的添加,那么下面是關(guān)于1,2,3,4的定義:

一:任務(wù)比較重要,但相應(yīng)的時間也很緊

二:任務(wù)是長期任務(wù),但比較重要

三:不那么重要的任務(wù),時間也很多

四:不需要多長時間的非重要任務(wù)

現(xiàn)在分析下上面的這些:
對于一:往往這個時候處于時間的dead line狀態(tài),而此時往往是我們都不想要的,熟話說事情是急不來的,這個時候往往會導(dǎo)致質(zhì)量的下降.

對于二:我們有充足的時間來做重要的任務(wù),這正是我們想要的,但,怎么做才能使其不會過渡到區(qū)間一呢,轉(zhuǎn)為區(qū)間1往往會由于人的惰性產(chǎn)生的,關(guān)鍵是要提前做事.安排好時間.

對于三:往往是一些可以輔助我們成長的事情,這些東西對我們有益處,這對全面的發(fā)展起到了很好的作用,-_-''就象我學(xué)吉他..

對于四:是些時間緊,但不重要的任務(wù),比如要幫助人去google一些資料.

從上面可以看到,區(qū)間一實際上是最差的,但為了做好區(qū)間2,我們必須要盡量減少區(qū)間4的份量,而對于全面的發(fā)展,我們也要安排時間到區(qū)間3.這也是很重要的.

posted @ 2007-02-11 15:54 agerlis 閱讀(370) | 評論 (0)編輯 收藏

前幾天一個朋友給我看了1段代碼:
any temp; //any is a class
temp = 1;
temp = "a";
temp = x; //x is a abstract class

看到這段代碼著實下了1跳.初期的感覺象void*指針那樣,又象variant變量。但感覺還是比較新穎的,-_-''也許我是菜鳥的原因,在腦袋轉(zhuǎn)了一下后,我實現(xiàn)了自己的一個類,用來接受任何參數(shù),起初我認(rèn)為any應(yīng)該是個typedef,而接收的類型也是前面知道的(-_-''又沒弄清需求就去實現(xiàn)了),所以實現(xiàn)一個接收任何參數(shù)的類需要個typelist,和對每種類型的泛化,下面是class的定義:

template<typename _typelist>
class?any
{
public:
?typedef typename Loki::TL::TypeAtNonStrict<_typelist,0>::Result?param1;
?typedef typename Loki::TL::TypeAtNonStrict<_typelist,1>::Result?param2;
?typedef typename Loki::TL::TypeAtNonStrict<_typelist,2>::Result?param3;
?typedef typename Loki::TL::TypeAtNonStrict<_typelist,3>::Result?param4;
?typedef typename Loki::TL::TypeAtNonStrict<_typelist,4>::Result?param5;

?any(param1 param):
??m_param1(param){}

?any(param2 param):
??m_param2(param){}

?any(param3 param):
??m_param3(param){}

?any(param4 param):
??m_param4(param){}

?template<typename _Ty>
?const _Ty&??Get()
?{
???? class?CERROR_ACCESS_DENIED;
???? LOKI_STATIC_CHECK((Loki::TL::IndexOf<_typelist,_Ty>::value != -???? 1),CERROR_ACCESS_DENIED);

???? return?__Access<_Ty>();
?}
private:
?template<typename _Ty>
?_Ty&? __Access();

?template<>
?param1& __Access<param1>() {return m_param1;}

?template<>
?param2& __Access<param2>() {return m_param2;}

?template<>
?param3& __Access<param3>() {return m_param3;}

?template<>
?param4& __Access<param4>() {return m_param4;}

?param1??m_param1;
?param2??m_param2;
?param3??m_param3;
?param4??m_param4;
};

typedef any<Loki::TYPE_LIST_3(int,float,char)>?ANY;

這樣似乎就可以接收任何類型了,也可以取出數(shù)據(jù),取出時必須要知道相應(yīng)的類型,而且,假如類型不在列表里面,則編譯期出錯
class?CERROR_ACCESS_DENIED;
LOKI_STATIC_CHECK((Loki::TL::IndexOf<_typelist,_Ty>::value != -???? 1),CERROR_ACCESS_DENIED);
這樣,-_-''似乎就可以了,只要所接收的類型可以拷貝即可。但有個明了的缺陷,那1就是接收的類型必須編譯期寫死,假如不寫死的話,我個人開始的認(rèn)為是加一個基類,-_-''
還是要3q我那位朋友,讓我了解到boost::any的用法
下面是boost::any的具體分析,我們要達到下面幾個要求:
1:可以接收任何類型的數(shù)據(jù)(具有value屬性)
2: 可以方便的取出數(shù)據(jù)
3:型別安全,不象void*
下面是boost::any的實現(xiàn),我按部分貼,而且省去我認(rèn)為不重要的東西,因為太長了,這會影響我blog的收視率。
1:首先來看下他的構(gòu)造和稀構(gòu)(-_-''錯別字)
?any()
????: content(0)
{
}
?
?template<typename ValueType>
?any(const ValueType & value)
????: content(new holder<ValueType>(value))
{
}
?
any(const any & other)
????: content(other.content ? other.content->clone() : 0)
?{
?}
?
?~any()
?{
?????delete content;
?}
從構(gòu)造函數(shù)可以看到,any可以接受默認(rèn)的,任何其他值包括ant本身,在稀構(gòu)里面可以看到對content的釋放,content在這里是一個基類的指針,是any內(nèi)部實現(xiàn)的,我們可以看到,在對any構(gòu)造是有種方法:
(1)content(new holder<ValueType>(value))
(2)content(other.content ? other.content->clone() : 0)
稍后會看到holder是派生自content類型的一個模板實現(xiàn),也許講到這里,有些應(yīng)該明白了any是怎么保存任何類型的吧,對于其他any的構(gòu)造,我們發(fā)現(xiàn)調(diào)用了content的一個clone方法,很明顯這是content的一個虛方法,這個方法的存在得以讓我們運用虛函數(shù)的機制正確的拷貝對象,下面會看到這只是個簡單的new操作。
2:來看下any的operator =的重載
any & swap(any & rhs)
{
?????std::swap(content, rhs.content);
?????return *this;
}
?
template<typename ValueType>
any & operator=(const ValueType & rhs)
{
????any(rhs).swap(*this);
????return *this;
}
?
any & operator=(const any & rhs)
{
??????any(rhs).swap(*this);
??????return *this;
}
可以看到operator =,接收任何其他類型的參數(shù),swap方法的實現(xiàn),用來交換2個對象的content指針,我們可以看到operator =里面臨時對象的構(gòu)建,在函數(shù)結(jié)束后,自動釋放原來content的對象,這有點RAII味道。(http://blog.sina.com.cn/u/1019039487)獨家小菜。。
3:下面來看下輔助類
?bool empty() const
?{
??????return !content;
?}
?
?const std::type_info & type() const
?{
??????return content ? content->type() : typeid(void);
?}
可以看到。一個empty,一個type,很形象。
4:下面來看下上面content所指的對象,以及any怎么保存任何類型,以及這種怎么保證型別安全
class placeholder
{
public: // structors
?????virtual ~placeholder()
?????{
?????}
public: // queries
??????virtual const std::type_info & type() const = 0;
??????virtual placeholder * clone() const = 0;
};
?
template<typename ValueType>
class holder : public placeholder
{
public: // structors
?????holder(const ValueType & value)
????????????? : held(value)
?????{
?????}
public: // queries
?????virtual const std::type_info & type() const
?????{
?????????return typeid(ValueType);
?????}
?
?????virtual placeholder * clone() const
?????{
??????????return new holder(held);
?????}
public: // representation
?????ValueType held;
};(-_-''格式矯正真是類啊)
?
placeholder就是上面content指向的對象,可以看到他定義的一些提供給any調(diào)用的函數(shù)和虛基本必須的虛稀構(gòu)函數(shù)(可以看到any對content調(diào)用了delete)
下面是holder的實現(xiàn),holder是一個模板,里面定義的
ValueType held;
很明星是any用來保存任何類型的,回顧下上面所說的any初始化content的2種方法
(1)content(new holder<ValueType>(value))
(2)content(other.content ? other.content->clone() : 0)
從這個地方可以看到怎么初始化holder對象,并保存到content.注意到這里的held是public的,這樣就提供了對數(shù)據(jù)訪問的功能,在訪問的時候必須要知道具體要訪問的類型,才能調(diào)用相應(yīng)的static_cast或者dynamic_cast來操作,而這樣其實也提供了型別安全的保證,eg:不象malloc,返回void*,然后()轉(zhuǎn)換一下。
5:看下怎么訪問any里面的屬性值:這里就不列舉出所有的實現(xiàn),因為有些是對const的版本。
template<typename ValueType>
ValueType * any_cast(any * operand)
{
????return operand && operand->type() == typeid(ValueType)
??????????????????? ? &static_cast<any::holder<ValueType> *>? (operand->content)->held
??????????????????? : 0;
}
?
template<typename ValueType>
ValueType any_cast(const any & operand)
{
?????typedef BOOST_DEDUCED_TYPENAME??????? remove_reference<ValueType>::type nonref;
?
???const nonref * result = any_cast<nonref>(&operand);
???if(!result)
??????????? boost::throw_exception(bad_any_cast());
????return *result;
}//這里去掉1些原來實現(xiàn)的代碼和注釋
可以看到具體的實現(xiàn)方式&dynamic_cast的邏輯差不多,對引用的cast有可能拋出異常。通過上面這種方式,就達到了對數(shù)據(jù)的讀取,讀取時必須知道里面的數(shù)據(jù)類型。可以看出any只能保存一個值,-_-''不向我那個,可以同時保存不同類型的值。
6:extension
可以通過std::vector<boost::any> anys,來構(gòu)建一個任何類型的列表,但訪問比較麻煩。
也可以通過any來達到虛函數(shù)不能為template的限制(因為一個是靜態(tài)的一個是動態(tài)的)
象下面:
class CBase
{
?public:
???? virtual void Set(boost::any) = 0;
};
?
class CHild:
???? public CBase
{
?public:
???? virtual void Set(boost::any param)
???? {
????????? m_value = param;
???? }
?private:
???? boost::any? m_value;
};
?
CHild?test;
CBase* ptr = &test;
ptr->Set(1);
ptr->Set('a');
7.finish...總算完成了...-_-''要變唐僧了...
????????????????????????????????????????????????? alex. agerlis@163.com
posted @ 2007-02-11 15:54 agerlis 閱讀(438) | 評論 (0)編輯 收藏

abstract factory.感覺是個很玄的名字,即使在我寫學(xué)習(xí)筆記的時候,我也因為缺少現(xiàn)實中的實踐而對其了解不深。^^希望.... 多指正
Name:
?? abstract factory
Addressed Problem:
?? 提供對同1種相關(guān)對象的創(chuàng)建。比如在程序里面,希望根據(jù)用戶配置來設(shè)置UI方案,比如方案1和2,對應(yīng)的UI也存在2套不同的實現(xiàn)類,比如對于ScrollBar,有CScrollBar1和CScrollBar2,都繼承自ScrollBar。也許在程序里面有很多這樣的類。這樣你在應(yīng)用UI實例化類時就必須要選擇比如
IScrollBar* pScrollBar = NULL;
if (_use_ui_1)
?? pScrollBar = new CScrollBar1;
else
?? pScrollBar = new CScrollBar2;
也許你這樣感覺沒多大關(guān)系,但想象下,在程序的多處都存在這樣的選擇,為什么我不選擇一種less error phone的方法呢?比如
pScrollBar = Create(...);
這樣一種簡單的方式呢?而且上面的寫法也引進了1個避短,也就是在產(chǎn)生pScrollBar時,涉及到了具體的實現(xiàn)類,這在面向?qū)ο筮@種program to interface這樣的語言中是很忌諱的事情。比如,在加種UI方案,也許你會再寫個else,這樣等于自己把自己往火堆里面推。你是一個勤奮的程序員,但不是個優(yōu)秀的程序員^^.也許有人會說,我可以利用prototype這樣的方式來啊。這樣,在程序的外面配置一下每個類的prototype就可以了,或許也可以用object factory啊,都可以(^^似乎是哦,我也沒學(xué)過這2個的說)解決上面的問題,一個通過DoClone類似的,1個通過ID或其他的,其實在應(yīng)用上面的2種時,自然的導(dǎo)出了abstract factory.為什么呢,因為上面的2種,你都需要設(shè)置多個的原型或ID。比如也許在CUIManager的構(gòu)造里面寫賊大的if
if (_use_ui_1)
{
??? ...//設(shè)置UI_1下所有的prototype
}
else
{
??? ...//設(shè)置UI_2下所有的prototype
}
也許在將來的莫天,在加上UI_3,則。再寫個if.也許大家可能會想,我在應(yīng)用ui時,我就知道了所要創(chuàng)建的對象,為什么我不把上面寶裝一下改成:
if (_use_ui_1)
?//設(shè)置factory_1
else
?//設(shè)置factory_2
然后在抽象出來的IFactory里面提供創(chuàng)建這些UI Class的方法,比如,CreateScrollBase.等等,這樣就有了abstract factory 的雛形。
基礎(chǔ)實現(xiàn)
/*
?測試abstract factory模式
*/

class?IScrollWindow
{
public:
?virtual void?DrawScroll(void) = 0;
};

class?IListWindow
{
public:
?virtual?void?DrawList(void) = 0;
};

class?ICreateWindowFactory
{
public:
?virtual?IScrollWindow*?CreateScrollWindow(void) = 0;

?virtual?IListWindow*?CreateListWindow(void) = 0;
};

class?CBlueWindowFactory:
?public?ICreateWindowFactory
{
?class?CBlueScrollWindow:
??public?IScrollWindow
?{
?public:
??virtual void?DrawScroll(void)
??{
???std::cout << "draw blue scroll" << std::endl;
??}
?};

?class?CBlueListWindow:
??public?IListWindow
?{
?public:
??virtual?void?DrawList(void)
??{
???std::cout << "draw blue list" << std::endl;
??}
?};
public:
?virtual?IScrollWindow*?CreateScrollWindow(void)
?{
??return?new CBlueScrollWindow;
?}

?virtual?IListWindow*?CreateListWindow(void)
?{
??return?new CBlueListWindow;
?}
};

class?CRedWindowFactory:
?public?ICreateWindowFactory
{
?class?CRedScrollWindow:
??public?IScrollWindow
?{
?public:
??virtual void?DrawScroll(void)
??{
???std::cout << "draw red scroll" << std::endl;
??}
?};

?class?CRedListWindow:
??public?IListWindow
?{
?public:
??virtual?void?DrawList(void)
??{
???std::cout << "draw red list" << std::endl;
??}
?};
public:
?virtual?IScrollWindow*?CreateScrollWindow(void)
?{
??return?new CRedScrollWindow;
?}

?virtual?IListWindow*?CreateListWindow(void)
?{
??return?new CRedListWindow;
?}
};
在需要用的地方,就可以這樣:
ICreateWindowFactory*?pCreateWindow1?= new CBlueWindowFactory;

?pCreateWindow1->CreateListWindow()->DrawList();
?pCreateWindow1->CreateScrollWindow()->DrawScroll();
假如需要用不同的工廠,則更換不會影響到調(diào)用處的代碼。因為掉用工廠的地方是面向接口的。其實abstract factory的理念應(yīng)該是比較簡單的(^^瞎猜的).基本講完了什么是抽象類工廠,他要解決的一些問題以及怎么解決和1個小而亂的demo代碼段。下面來看下我們怎么泛化這個類工廠,這個會涉及到loki里面的具體實現(xiàn),大家要加滿油啊,因為泛化類工廠是一件不容易的事情啊。

泛化_1
首先,(^^這部分我也不是很懂)要泛化的是abstract factory的接口,就象上面的CreateScrollWindow和CreateListWindow,在泛化時需要的信息是要創(chuàng)建的同1組對象的相關(guān)接口比如IScrollBar,IList等等,在loki里面,要為1個類泛化1組接口,可以通過GenScatterHierarchy來將unit應(yīng)用到typelist里的每1個類型,并將該類從unit<type>派生,從而得到1組接口。GenScatterHierarchy做了什么呢,他產(chǎn)生了啥呢?具體的可以看morden c++里面的實現(xiàn)。通過GenScatterHierarchy我們得到了我們要得1組接口。下面是loki里面對這個得相關(guān)實現(xiàn)
template <class T>
class AbstractFactoryUnit
{
public:
????virtual T* DoCreate(Type2Type<T>) = 0;
????virtual ~AbstractFactoryUnit() {}
};

可以看到,上面定義了2個函數(shù),而這個類就是我上面說得調(diào)用GenScatterHierarchy時,具現(xiàn)化時對typelist得每個類型應(yīng)用得template類,而最后產(chǎn)生得也將是類似AbstractFactoryUnit<IScrollBar>的類,我們具體的抽象工廠從這些派生。至于pure dctor這個大家應(yīng)該都知道啥作用。下面來看Abstract Factory 的泛化:

template
<
????class TList,
????template <class> class Unit = AbstractFactoryUnit
>
class AbstractFactory : public GenScatterHierarchy<TList, Unit>
{
public:
?????typedef TList ProductList;
???????
?????template <class T> T* Create()
?????{
????????Unit<T>& unit = *this;
????????return unit.DoCreate(Type2Type<T>());
?????}
?};
可以看到這個即由GenScatterHierarchy來得到了我們想要的東西。提供了Create的模板函數(shù),使得我們可以象這樣factory.Create<IScrollBar>()的方便形勢來調(diào)用。ProductList是對于抽象工廠要創(chuàng)建的類型的重命名。方便后面在產(chǎn)生實際的類型時,獲取對應(yīng)的類型信息,對于DoCreate的參數(shù),大家應(yīng)該都明白這是重載用的,那用在哪里呢?下面會介紹。

泛化_2
在辛苦介紹完泛化抽象工廠的接口后,我們可以通過類似的方式來定義1個abstract factory的接口
Loki::AbstractFactory<LOKI_TYPELIST_2(IScrollBar,IListWindow)>
下面我們來介紹最后的,我們怎么來提供抽象工廠的實現(xiàn),首先是對象的創(chuàng)建,loki里面提供了默認(rèn)的創(chuàng)建的方法,當(dāng)然我們可以修改或用特化的版本來做選擇。
template <class ConcreteProduct, class Base>
class OpNewFactoryUnit : public Base
{
???? typedef typename Base::ProductList BaseProductList;
???
protected:
?????typedef typename BaseProductList::Tail ProductList;
???
public:
?????typedef typename BaseProductList::Head AbstractProduct;
?????ConcreteProduct* DoCreate(Type2Type<AbstractProduct>)
?????{
????????? return new ConcreteProduct;
?????}
};
可以看到DoCreate是我們的核心部分,里面調(diào)用了new來創(chuàng)建對象。而這里也讓我們看到這應(yīng)該是上面創(chuàng)建對象的重載。而Type2Type的作用正是在這里體現(xiàn)作用,因為c++無法通過函數(shù)返回值來重載不同的對象。也許你會看到上面的一些類型定義,包括OpNewFactoryUnit的2個模板參數(shù),第2個模板參數(shù)是實現(xiàn)GenLinearHierarchy必備的GenLinearHierarchy和上面的GenScatterHierarchy的核心思想一樣,都是通過具現(xiàn)化來實現(xiàn)的,不過GenLinearHierarchy產(chǎn)生的是線性的繼承體系,中間夾雜著比如OpNewFactoryUnit<IScrollBar,GenLinearHierarchy<...> >這樣的形勢。下面來看下抽象工程的具體實現(xiàn)的泛化,聯(lián)系起來就能對上面的理解了
template
<
????class AbstractFact,
????template <class, class> class Creator = OpNewFactoryUnit,
????class TList = typename AbstractFact::ProductList
>
class ConcreteFactory
?????: public GenLinearHierarchy<
?????typename TL::Reverse<TList>::Result, Creator, AbstractFact>
{
public:
????typedef typename AbstractFact::ProductList ProductList;
????typedef TList ConcreteProductList;
};
可以看到ConcreteFactory由GenLinearHierarchy來驅(qū)動產(chǎn)生我們想要的,本來這個貼圖比較明朗點,但我懶的畫,哈哈。從GenLinearHierarchy的參數(shù)來看,第1個是具體的實現(xiàn)類的typelist,比如LOKI_TYPELIST2(CScrollBar_1,CListWindow_1),至于為什么要對類型做reverse操作,因為在類的基礎(chǔ)體系產(chǎn)生后,typelist的第1個元素,在繼承體系是由下往上的,而于上面由OpNewFactoryUnit等定義的ProductList的Head定義的自上往下的是相反的,所以這里應(yīng)用了reverse操作。Creator就是上面的OpNewFactoryUnit或你自定義的元素。并在具現(xiàn)化是,應(yīng)用typelist的每個類型。AbstractFact是繼承體現(xiàn)的最頂端,這個應(yīng)該很明顯,就是上面定義的AbstractFactory,這樣啥都明確了,具體的接口,對接口的函數(shù)的重載都已經(jīng)泛化完成。下面是(^^睡死了,睡覺去了,簡單從便,上面均未調(diào)試哦).至于為什么會把第3個參數(shù)默認(rèn)為抽象類工廠接口的ProductList,這個和loki用基于prototype的Creator有關(guān)系。。(^^俺是菜鳥,就只能到這里了)
對abstract factory的看法,優(yōu)點在上面的已經(jīng)說過了,確定在,我們要添加1種對象的創(chuàng)建時,都要去修改接口的定義,當(dāng)然后面的泛化也為我們解決了些問題,但泛化對于參數(shù)的傳遞不怎么好用,可以通過提供新的OpNewFactoryUnit來適當(dāng)解決。
??????????????????????????????????????????????????? agerlis.2007.2.10 0:22
posted @ 2007-02-11 15:53 agerlis 閱讀(400) | 評論 (0)編輯 收藏

以前C讀取命令行參數(shù)感覺太麻煩,而且不容易記憶.下面是另外一種命令行的讀取方法
通過GetCommandLine(),來返回當(dāng)前的命令行:
setlocale(LC_ALL, ".ACP");
std::wcout << GetCommandLine() << std::endl;
下面是輸出:
"e:\學(xué)習(xí)程序\consol3\debug\consol3.exe" a b c
對于命令行的參數(shù)讀取用CommandLineToArgvW,可以把命令行參數(shù)轉(zhuǎn)換成字符串?dāng)?shù)組的形式
int?nums = 0;
TCHAR** temp = CommandLineToArgvW(GetCommandLine(),&nums);
for(int i = 0; i < nums; i++)
{
? std::wcout<< temp[i] << std::endl;
}
下面是輸出:
e:\學(xué)習(xí)程序\consol3\debug\consol3.exe
a
b
c

可以看到命令行參數(shù)從下標(biāo)=1的元素開始.
感覺這種形式比較好記憶
posted @ 2007-02-11 15:53 agerlis 閱讀(1002) | 評論 (0)編輯 收藏

handle-body,睡死了,但還是得堅持下。其實這個是很簡單的概念
這個也稱呼為pimpl,是private implemention的縮寫,下面涉及到的都叫做pimpl, 那用這個到底有什么好處呢:
1:可以把具體的實現(xiàn)從client端封裝,這樣即使修改實現(xiàn),只要不修改頭文件,對client端來說,是沒有任何影響的,甚至不改變代碼的2進制特性
2:加速編譯時間,我們知道有時頭文件有太多的實現(xiàn),會導(dǎo)致包含這個頭文件的其他文件的編譯時間增加,通過pimpl,我們把實現(xiàn)從頭文件移到cpp里面,從而減少了其他包含這個文件的編譯時間,加快編譯速度
3:減少依賴,這個實際上也增加了編譯的速度,可以不對client端暴露一些實現(xiàn)上的頭文件,從而減少了依賴說了這么多,下面來看下一個簡單的pimpl的實現(xiàn)。是用loki的類來實現(xiàn)的。哈哈,睡死了,偷懶
/*.h*/
class CTest
{
public:
??? void Test();
private:?
????Loki::PimplT::Type m_impl;
};
------------------------------------------------------------------- /*.cpp*/
template<>
struct Loki::ImplT
{
public:
?? ?void Test() { std::cout << "test" << std::endl; }
};

void CTest::Test() { return m_impl->Test(); }

上面只是個很簡單很簡單的例子,以至于有些還無法體會到pimpl的作用,但相信在實踐中你會體會到,把原來定義在CTest里面的一些私有的方法,成員,全部挪到ImplT里面時,你會體會到,這個CTest的頭文件里include了很少的頭,他可以說完成了原始的使命,達到了功能性接口的作用,而其他原來定義在頭里的.h,可以全部挪到cpp里了。下面來分析下loki是怎么實現(xiàn)的。可以看到實現(xiàn)pimpl首先需要牽置聲明pre define類,loki通過模板的全特化來實現(xiàn)了這個的隱藏,從而避免了把具體的實現(xiàn)類暴露給client的弊端。下面來看下這個泛化的pre define: template struct ImplT; 哈哈,很簡單,再看上面我的cpp里的定義,大家結(jié)合上面也許就明白了吧,部過,這里需要注意的是,CTest的構(gòu)造函數(shù)要寫后面,不然can;t compile. 但是,為什么具體的實現(xiàn)類是ImplT但,前面的
Loki::PimplT::Type m_impl;
那Loki::PimplT::Type是什么用的,我們知道,假如保存原始的
Loki::ImplT<CTest>* m_impl;
然后new一個,其實這樣只存在1個問題,2個不方便,
1:問題是這樣的原始指針,不能傳播const信息,也就是說,對象CTest轉(zhuǎn)為const的化,他里面的指針類型不是同樣隨著帶有const屬性,也就是說,假如此時指針指向的對象有個函數(shù),提供了const&none const的,此時,還是會調(diào)用non const的,所以,外界還是可以通過這個對象來做修改。
2:2個不方便是,你必須對對象實現(xiàn)new和delete.
下面來看下loki是怎么做的
template<class T>
struct ConstPropPtr
{
??????? explicit ConstPropPtr(T* p) : ptr_(p) {}
??????? ~ConstPropPtr() { delete? ptr_; ptr_ = 0; }
??????? T* operator->()??? { return? ptr_; }
??????? T& operator*()??? { return *ptr_; }
??????? const T* operator->() const??? { return? ptr_; }
??????? const T& operator*()? const??? { return *ptr_; }
???
private:
??????? ConstPropPtr();
??????? ConstPropPtr(const ConstPropPtr&);
??????? ConstPropPtr& operator=(const ConstPropPtr&);
??????? T* ptr_;
};

這個類提供了對問題1的解決。下面會講解,主要的點是,對象不同于指針,對象能傳遞const屬性。
下面看下pimlT的定義:
template<class T, template<class> class Ptr = ConstPropPtr>
struct PimplT
{
??????? typedef T Impl;

??????? // declare pimpl
??????? typedef Pimpl<ImplT<T>, Ptr<ImplT<T> > > Type;

??????? // inherit pimpl
??????? typedef PimplOwner<ImplT<T>, Ptr<ImplT<T> > > Owner;
};
可以看到對Type
的定義,下面的owner也不說了,直接到Pimpl,

template
<???
??????? class T,
??????? typename Pointer = ConstPropPtr<T>
>
class Pimpl
{
public:

??????? typedef T Impl;

??????? Pimpl() : ptr_(new T)
??????? {}

??????? ~Pimpl()
??????? {
??????????? typedef char T_must_be_defined[sizeof(T) ? 1 : -1 ];
??????? }


??????? T* operator->()
??????? {
??????????? return ptr_.operator->();
??????? }

??????? T& operator*()
??????? {
??????????? return ptr_.operator*();
??????? }

??????? const T* operator->() const
??????? {
??????????? return ptr_.operator->();
??????? }

??????? const T& operator*() const
??????? {
??????????? return ptr_.operator*();
??????? }

??????? Pointer& wrapped()
??????? {
??????????? return ptr_;
??????? }

??????? const Pointer& wrapped() const
??????? {
??????????? return ptr_;
??????? }


private:
??????? Pimpl(const Pimpl&);
??????? Pimpl& operator=(const Pimpl&);

??????? Pointer ptr_;
};

可以看到,這個類用了上面的ConstPropPtr從而使對象有了const屬性的傳遞。其他的,實際上,幫你操作了new,再ConstPropPtr里釋放,有點RAII的味道,剩下的完全模擬保存的指針的行為,即implT的實現(xiàn),從而使其能正確的操作對象。
睡死了,早早結(jié)束
???????????????????????????????????????????????? alex_yuu
posted @ 2007-02-11 15:52 agerlis 閱讀(425) | 評論 (0)編輯 收藏

我的msn:agerlis@163.com
我的email:agerlis@163.com
我的qq:350457656
posted @ 2007-02-11 15:32 agerlis 閱讀(345) | 評論 (3)編輯 收藏

僅列出標(biāo)題  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产99精品国自产| 亚洲视频在线观看免费| 亚洲综合不卡| 亚洲主播在线观看| 国产综合色在线| 亚洲第一精品电影| 欧美成人中文| 午夜精品一区二区三区四区| 亚洲欧美日韩专区| 亚洲国产美女| 亚洲欧美另类在线观看| 在线免费观看视频一区| 亚洲图片欧美一区| 亚洲人体1000| 亚洲欧美日韩国产综合在线| 亚洲韩国一区二区三区| 亚洲一区二区三区精品视频| 伊人久久婷婷| 亚洲一区二区三区免费观看| 亚洲国产精品小视频| 中文在线一区| 亚洲精品国精品久久99热一| 西西裸体人体做爰大胆久久久| 欧美成人a视频| 久久成人免费| 欧美日韩亚洲网| 噜噜噜91成人网| 国产精品影片在线观看| 亚洲国产精品va在线观看黑人| 国产精品成人av性教育| 欧美成人精品高清在线播放| 国产精品国产一区二区| 91久久精品国产91久久性色tv| 国产精品亚洲不卡a| 亚洲大片免费看| 一区二区三区在线观看视频| 亚洲欧美bt| 国产精品99久久久久久人| 狂野欧美性猛交xxxx巴西| 欧美诱惑福利视频| 欧美色网在线| 亚洲精品一区二区三| 91久久中文| 卡一卡二国产精品| 欧美大片在线看免费观看| 伊人久久综合97精品| 午夜精品一区二区三区四区 | 午夜精品影院| 欧美日韩美女一区二区| 黑人巨大精品欧美一区二区小视频 | 久久国产精品99精品国产| 国产亚洲精品资源在线26u| 欧美女激情福利| 免费亚洲电影| 免费亚洲婷婷| 欧美激情视频在线播放| 欧美成人亚洲成人| 欧美福利在线| 免费成人av在线| 欧美精品免费观看二区| 国产精品大片| 国产精品伦理| 亚洲国产欧美一区二区三区久久| 国产偷久久久精品专区| 国产在线播精品第三| 亚洲美女性视频| 久久久久久久尹人综合网亚洲| 久久久久欧美精品| 亚洲激情在线视频| 一区二区日韩| 久久久中精品2020中文| 欧美性色视频在线| 亚洲黄色尤物视频| 欧美一区精品| 日韩视频不卡中文| 欧美一站二站| 国产精品日日摸夜夜添夜夜av| 国产日韩精品电影| av成人毛片| 亚洲人成网站色ww在线| 久久精品一区二区三区四区| 美日韩精品视频免费看| 国产区亚洲区欧美区| 亚洲一区中文字幕在线观看| 亚洲春色另类小说| 欧美中文在线免费| 欧美电影免费观看高清| 久久久久.com| 国内精品美女在线观看| 香港成人在线视频| 亚洲视频免费在线观看| 国产精品国产三级国产专播精品人| 好看的av在线不卡观看| 欧美专区在线观看一区| 亚洲视频免费看| 国产精品欧美在线| 久久九九国产精品| 久久gogo国模裸体人体| 极品中文字幕一区| 亚洲国产精品悠悠久久琪琪| 欧美va亚洲va日韩∨a综合色| 伊人久久亚洲影院| 欧美激情无毛| 国产精品久久久久永久免费观看| 在线视频精品一区| 一本色道久久综合狠狠躁的推荐| 欧美粗暴jizz性欧美20| 在线午夜精品自拍| 午夜亚洲一区| 亚洲精品国精品久久99热一| 一区二区三区国产在线观看| 国产精品一区二区三区久久 | 欧美影院成人| 红桃视频国产精品| 亚洲精品国产拍免费91在线| 欧美视频中文字幕| 久久综合中文色婷婷| 欧美高清在线播放| 久久国产色av| 国产精品v欧美精品v日本精品动漫| 亚洲一区二区三区免费在线观看| 中文av一区特黄| 亚洲精品日韩激情在线电影| 午夜精品久久久久久久蜜桃app | 亚洲一区二区三区午夜| 国产一二精品视频| 亚洲一区二区三区高清| 亚洲精品久久久久久下一站| 欧美一区二区在线观看| 亚洲在线观看免费视频| 美女精品自拍一二三四| 久久国产主播精品| 国产亚洲欧美在线| 午夜精品剧场| 久久成人18免费网站| 国产欧美日韩精品丝袜高跟鞋| 蜜臀av一级做a爰片久久| 欧美激情第三页| 欧美激情综合色| 最新亚洲激情| 欧美日韩国产影片| 日韩一级片网址| 亚洲欧美成aⅴ人在线观看| 欧美午夜片在线免费观看| 亚洲精品资源美女情侣酒店| 亚洲一区国产精品| 国产欧美日韩免费看aⅴ视频| 亚洲国产美女久久久久| 亚洲视频第一页| 亚洲深夜av| 嫩模写真一区二区三区三州| 欧美成年人网站| 最新国产成人在线观看| 亚洲一区二区在线视频| 国内精品99| 国产精品高潮呻吟久久| 久久天天躁夜夜躁狠狠躁2022| 欧美一区二区三区在线看| 国产区精品视频| 欧美喷潮久久久xxxxx| 午夜久久影院| 亚洲精品一区二区三区蜜桃久| 亚洲视频一区二区在线观看| 极品少妇一区二区| 国产麻豆视频精品| 欧美午夜视频一区二区| 久久精品一区| 午夜精品美女久久久久av福利| 另类春色校园亚洲| 欧美一区在线视频| 亚洲四色影视在线观看| 最新中文字幕亚洲| 在线播放亚洲| 久久久久久久欧美精品| 欧美激情精品久久久久久黑人| 亚洲午夜女主播在线直播| 亚洲国产精品va| 在线观看不卡av| 国产精品久久中文| 国产精品s色| 国产精品av免费在线观看| 欧美另类高清视频在线| 欧美极品一区二区三区| 欧美韩日一区二区| 欧美日韩国产在线| 国产精品久久久久久久9999| 欧美国产激情| 欧美精品一区二区精品网 | 久久精品一级爱片| 久久精品国产久精国产爱| 久久蜜桃资源一区二区老牛| 久久一区二区三区av| 你懂的成人av| 亚洲高清视频的网址| 亚洲精品视频免费| 夜夜夜久久久| 久久久噜噜噜久久| 欧美二区视频| 国产精品成人一区二区| 好看的av在线不卡观看|