C++實現的委託機制
1.引言
下面的委託實現使用的MyGUI裡面的委託實現,MyGUI是一款強大的GUI庫,想理解更多的MyGUI資訊,猛擊這裡http://mygui.info/
最終的程式碼可以在這裡下載:http://download.csdn.net/detail/gouki04/3641328 我們的目標是要實現一個跟.NET幾乎完全一樣的委託,使用簡單,支援多播,可以新增刪除委託。同時支援C++的普通函式、模板函式、類成員函式,類的靜態成員函式,並且支援多型。使用方式如下:
- // 普通函式
- void normalFunc(){ cout << "func1" << endl; }
- class
- {
- public:
- // 類成員函式
- void classFunc(){ cout << "Base func1" << endl; }
- };
- int main()
- {
- Base b;
- CMultiDelegate myDelegate;
- myDelegate += newDelegate(normalFunc);
- myDelegate += newDelegate(&b, &Base::classFunc);
- myDelegate(); // 此時會呼叫normalFunc和classFunc
- myDelegate -= newDelegate(&b, &Base::classFunc);
- myDelegate(); // 此時會呼叫normalFunc
- return 0;
- }
2.實現無參函式委託
要實現委託,首先要解決的是封裝C++中的函式指標。因為在C++中,普通函式指標和類成員函式指標是完全不一樣的。如下例子
- class CMyClass
- {
- public:
- void func(int);
- };
- // 定義一個指向CMyClass型別,引數列表為(int),返回值為void的函式指標
- typedefvoid (CMyClass::*ClassMethod) (int); // 注意定義時使用了特殊的運算子::*
那麼此函式指標只能指向CMyClass型別的成員函式,不能指向其他類或者普通函式
類成員函式指標不能直接呼叫,要通過一個類例項來呼叫,如下
- CMyClass *object = new CMyClass;
- ClassMethod method = CMyClass::func;
- (object->*method)(5); // 注意呼叫時使用了特殊運算子->*
那麼如何封裝呢?我們先來定義下介面吧
(為了簡單起見,下面的實現都是以無參函式為例,後續會講到如何支援任意引數)
- class IDelegate
- {
- public:
- virtual ~IDelegate() { }
- virtualbool isType(const std::type_info& _type) = 0;
- virtualvoid invoke() = 0;
- virtualbool compare(IDelegate *_delegate) const = 0;
- };
IDelegate類的介面很少,也很簡單,必要介面只有一個,就是invoke,用於觸發函式
但為了可以方便管理,使用了isType和compare函式來進行相等判斷。
下面是封裝的普通函式指標
- class CStaticDelegate : public IDelegate
- {
- public:
- typedefvoid (*Func)();
- CStaticDelegate(Func _func) : mFunc(_func) { }
- virtualbool isType( const std::type_info& _type) { returntypeid(CStaticDelegate) == _type; }
- virtualvoid invoke() { mFunc(); }
- virtualbool compare(IDelegate *_delegate) const
- {
- if (0 == _delegate || !_delegate->isType(typeid(CStaticDelegate)) ) returnfalse;
- CStaticDelegate * cast = static_cast<CStaticDelegate*>(_delegate);
- return cast->mFunc == mFunc;
- }
- private:
- Func mFunc;
- };
可以看到,CStaticDelegate只是簡單地封裝了普通函式指標,程式碼也非常簡單
(類的某些成員函式,如isType和compare使用了RTTI,
好了,注意了,下面開始封裝類成員函式指標
- template<class T>
- class CMethodDelegate : public IDelegate
- {
- public:
- typedefvoid (T::*Method)();
- CMethodDelegate(T * _object, Method _method) : mObject(_object), mMethod(_method) { }
- virtualbool isType( const std::type_info& _type) { returntypeid(CMethodDelegate) == _type; }
- virtualvoid invoke()
- {
- (mObject->*mMethod)();
- }
- virtualbool compare(IDelegate *_delegate) const
- {
- if (0 == _delegate || !_delegate->isType(typeid(CMethodDelegate)) ) returnfalse;
- CMethodDelegate* cast = static_cast<CMethodDelegate* >(_delegate);
- return cast->mObject == mObject && cast->mMethod == mMethod;
- }
- private:
- T * mObject;
- Method mMethod;
- };
首先解釋一下:因為類成員函式指標與類的型別有關,不同類的成員函式指標是不一樣的。
要解決型別不同,很簡單,使用模板就行。
程式碼跟CStaticDelegate基本一樣,下面稍微解釋一下:
CMethodDelegate類主要封裝了一個類例項指標以及類成員函式的指標
這樣在invoke時就不要額外的通過一個類例項了
要注意一點,compare函式的實現中,相等判定是類例項以及類函式指標都一樣。
也就是說就算是指標同一個成員函式,但例項不同,委託就不同
為了方便使用,定義函式newDelegate來建立委託使用的函式
- inline IDelegate* newDelegate( void (*_func)() )
- {
- returnnew CStaticDelegate(_func);
- }
- template<class T>
- inline IDelegate* newDelegate( T * _object, void (T::*_method)() )
- {
- returnnew CMethodDelegate<T>(_object, _method);
- }
至此,對C++函式指標的封裝就完成了,不難吧。
下面就是委託的實現了
- class CMultiDelegate
- {
- public:
- typedef std::list<IDelegate*> ListDelegate;
- typedef ListDelegate::iterator ListDelegateIterator;
- typedef ListDelegate::const_iterator ConstListDelegateIterator;
- CMultiDelegate () { }
- ~CMultiDelegate () { clear(); }
- bool empty() const
- {
- for (ConstListDelegateIterator iter = mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
- {
- if (*iter) returnfalse;
- }
- returntrue;
- }
- void clear()
- {
- for (ListDelegateIterator iter=mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
- {
- if (*iter)
- {
- delete (*iter);
- (*iter) = 0;
- }
- }
- }
- CMultiDelegate& operator+=(IDelegate* _delegate)
- {
- for (ListDelegateIterator iter=mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
- {
- if ((*iter) && (*iter)->compare(_delegate))
- {
- delete _delegate;
- return *this;
- }
- }
- mListDelegates.push_back(_delegate);
- return *this;
- }
- CMultiDelegate& operator-=(IDelegate* _delegate)
- {
- for (ListDelegateIterator iter=mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
- {
- if ((*iter) && (*iter)->compare(_delegate))
- {
- if ((*iter) != _delegate) delete (*iter);
- (*iter) = 0;
- break;
- }
- }
- delete _delegate;
- return *this;
- }
- void operator()( )
- {
- ListDelegateIterator iter = mListDelegates.begin();
- while (iter != mListDelegates.end())
- {
- if (0 == (*iter))
- {
- iter = mListDelegates.erase(iter);
- }
- else
- {
- (*iter)->invoke();
- ++iter;
- }
- }
- }
- private:
- CMultiDelegate (const CMultiDelegate& _event);
- CMultiDelegate& operator=(const CMultiDelegate& _event);
- private:
- ListDelegate mListDelegates;
- };
仔細理解下CMultiDelegate類的實現,程式碼都不深奧。
比較重要的是3個函式 :+=,-=,()運算子的過載函式
+= 用於新增一個委託函式
-= 用於去掉一個委託函式
() 用於觸發委託函式
差不多就是普通的stl容器使用了。
這裡要重點說明的一點是,大家仔細看 += 函式的實現中
- if ((*iter) && (*iter)->compare(_delegate))
- {
- delete _delegate; // 如果該委託函式已經被添加了,則delete掉外部的_delegate
- return *this;
- }
為什麼要delete掉外部的指標呢?
因為C++的記憶體洩露一直是個麻煩事,所以MyUGI的委託裡,所有的委託函式統一由Delegate本身管理
外部不要自己new或delete委託函式,也不要儲存一個委託函式,Delegate本身會管理好的。
建議像如下使用:
- CMultiDelegate myDelegate;
- myDelegate += newDelegate(normalFunc);
- myDelegate -= newDelegate(normalFunc);
而不建議像如下使用:
- CMultiDelegate myDelegate;
- IDelegate* delegateFunc = newDelegate(normalFunc);
- myDelegate += delegateFunc;
- myDelegate -= delegateFunc;
上面2種方法都沒錯,都不會造成記憶體洩露
你可能會覺得第2種方法減少new的次數,比第一種方法更好。其實不然,因為第2種方法有個很大的隱患
- myDelegate -= delegateFunc; // 在這一步,delegateFunc所指向的空間已經被釋放掉了(在-=函式裡面)
所以如果你後面又想將delegateFunc新增到myDelegate裡面時,你就不能再這樣用了
- myDelegate += delegateFunc; // 錯誤,因為delegateFunc的空間已經被釋放了
你得重新new一個
delegateFunc = newDelegate(normalFunc);
myDelegate += delegateFunc;
相信你不會願意這樣做的,因為這種方法很容易造成記憶體洩露或者崩潰
現在你應該可以明白 -= 函式是怎麼釋放委託函式記憶體了吧。
1.實現任意引數的函式委託
按上一篇文章的方法,你已經可以使用無引數的函式委託了。當然,這遠遠不夠。要實現任意引數的函式委託,這裡的任意引數包括任意個數和任意型別。任意型別這個容易解決,使用模板就行,但任意引數個數呢?
只能不同個數各實現一個類,如
- // 單參函式委託
- template<typename TP1>
- class CMultiDelegate1{};
- // 雙參函式委託
- template<typename TP1, typename TP2>
- class CMultiDelegate2{};
注意類名是不一樣的,分別為CMultiDelegate1和CMultiDelegate2
C++裡面,類名相同但模板引數個數不同是會當成一個類對待的,所以那樣編譯不過的
這樣是不是很麻煩呢?
不是很麻煩,是相當麻煩。因為不單單是CMultiDelegate要實現多個引數的版本
連IDelegate、CStaticDelegate和CMethodDelegate都要實現對應的多個引數的版本!
其實所有版本的內部實現幾乎一樣,下面給出雙參函式的版本
- template<typename TP1, typename TP2>
- class IDelegate2
- {
- public:
- virtual ~IDelegate2() { }
- virtualbool isType( const std::type_info& _type) = 0;
- virtualvoid invoke( TP1 p1, TP2 p2 ) = 0;
- virtualbool compare( IDelegate2<typename TP1, typename TP2> *_delegate) const = 0;
- };
- template<typename TP1, typename TP2>
- class CStaticDelegate2 : public IDelegate2<typename TP1, typename TP2>
- {
- public:
- typedefvoid (*Func)( TP1 p1, TP2 p2 );
- CStaticDelegate2 (Func _func) : mFunc(_func) { }
- virtualbool isType( const std::type_info& _type) { returntypeid( CStaticDelegate2<typename TP1, typename TP2> ) == _type; }
- virtualvoid invoke( TP1 p1, TP2 p2 )
- {
- mFunc( p1, p2 );
- }
- virtualbool compare( IDelegate2<typename TP1, typename TP2> *_delegate) const
- {
- if (0 == _delegate || !_delegate->isType(typeid(CStaticDelegate2 <typename TP1, typename TP2>)) ) returnfalse;
- CStaticDelegate2 <typename TP1, typename TP2> * cast = static_cast<CStaticDelegate2 <typename TP1, typename TP2> *>(_delegate);
- return cast->mFunc == mFunc;
- }
- virtualbool compare(IDelegateUnlink * _unlink) const { returnfalse; }
- private:
- Func mFunc;
- };
- template <typename T, typename TP1, typename TP2>
- class CMethodDelegate2 : public IDelegate2 <typename TP1, typename TP2>
- {
- public:
- typedefvoid (T::*Method)( TP1 p1, TP2 p2 );
- CMethodDelegate2(T * _object, Method _method) : mObject(_object), mMethod(_method) { }
- virtualbool isType( const std::type_info& _type) { returntypeid( CMethodDelegate2 <T, TP1, TP2> ) == _type; }
- virtualvoid invoke( TP1 p1, TP2 p2 )
- {
- (mObject->*mMethod)( p1, p2 );
- }
- virtualbool compare( IDelegate2 <typename TP1, typename TP2> * _delegate) const
- {
- if (0 == _delegate || !_delegate->isType(typeid(CMethodDelegate2 <T, TP1, TP2>)) ) returnfalse;
- CMethodDelegate2 <T, TP1, TP2> * cast = static_cast< CMethodDelegate2 <T, TP1, TP2> * >(_delegate);
- return cast->mObject == mObject && cast->mMethod == mMethod;
- }
- private:
- T * mObject;
- Method mMethod;
- };
- template <typename TP1, typename TP2>
- inline delegates::IDelegate2 <typename TP1, typename TP2> * newDelegate( void (*_func)( TP1 p1, TP2 p2 ) )
- {
- returnnew delegates::CStaticDelegate2 <typename TP1, typename TP2> (_func);
- }
- template <typename T, typename TP1, typename TP2>
- inline delegates::IDelegate2 <typename TP1, typename TP2> * newDelegate( T * _object, void (T::*_method)( TP1 p1, TP2 p2 ) )
- {
- returnnew delegates::CMethodDelegate2 <T, TP1, TP2> (_object, _method);
- }
- template <typename TP1, typename TP2>
- class CMultiDelegate2
- {
- public:
- typedef IDelegate2 <typename TP1, typename TP2> IDelegate;
- typedeftypename std::list<IDelegate*> ListDelegate;
- typedeftypename ListDelegate::iterator ListDelegateIterator;
- typedeftypename ListDelegate::const_iterator ConstListDelegateIterator;
- CMultiDelegate2 () { }
- ~CMultiDelegate2 () { clear(); }
- bool empty() const
- {
- for (ConstListDelegateIterator iter = mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
- {
- if (*iter) returnfalse;
- }
- returntrue;
- }
- void clear()
- {
- for (ListDelegateIterator iter=mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
- {
- if (*iter)
- {
- delete (*iter);
- (*iter) = 0;
- }
- }
- }
- CMultiDelegate2 <typename TP1, typename TP2> & operator+=(IDelegate* _delegate)
- {
- for (ListDelegateIterator iter=mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
- {
- if ((*iter) && (*iter)->compare(_delegate))
- {
- delete _delegate;
- return *this;
- //MYGUI_ASSERT(false, "dublicate delegate");
- }
- }
- mListDelegates.push_back(_delegate);
- return *this;
- }
- CMultiDelegate2 <typename TP1, typename TP2> & operator-=(IDelegate* _delegate)
- {
- for (ListDelegateIterator iter=mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
- {
- if ((*iter) && (*iter)->compare(_delegate))
- {
- if ((*iter) != _delegate) delete (*iter);
- (*iter) = 0;
- break;
- }
- }
- delete _delegate;
- return *this;
- }
- void operator()( TP1 p1, TP2 p2 )
- {
- ListDelegateIterator iter = mListDelegates.begin();
- while (iter != mListDelegates.end())
- {
- if (0 == (*iter))
- {
- iter = mListDelegates.erase(iter);
- }
- else
- {
- (*iter)->invoke( p1, p2 );
- ++iter;
- }
- }
- }
- private:
- CMultiDelegate2 (const CMultiDelegate2 <typename TP1, typename TP2> & _event);
- CMultiDelegate2<typename TP1, typename TP2> & operator=(const CMultiDelegate2<typename TP1, typename TP2> & _event);
- private:
- ListDelegate mListDelegates;
- };
當然放心啦,不會讓大家將不同引數的版本各寫一遍的
下面要介紹的是MyGUI的解決方法,一個利用預編譯和標頭檔案重複編譯的方法(很有意思的)
我們一般寫標頭檔案時,都會加上防止標頭檔案重複編譯的程式碼,如
- #ifndef __XXX_H__
- #define __XXX_H__
- // ..類宣告等
- #endif
這裡我們就要反其道而行,去掉防止重複編譯的程式碼,然後重複包含這個標頭檔案,但每次其編譯的都是不同引數個數的版本
第一次編譯的是無參的,第二次是單參的,第三次是雙參.....一直到你想要支援的引數個數
那怎麼讓其每次編譯的都不同呢?
答案就是使用強大的預編譯:巨集
下面給出單參的IDelegate的例子
首先定義以下巨集:
- #define DELEGATE_TEMPLATE template
- #define DELEGATE_TEMPLATE_PARAMS <typename TP1>
- #define DELEGATE_TEMPLATE_ARGS TP1 p1
- #define MYGUI_I_DELEGATE IDelegate1
那麼下面這段程式碼就會編譯出單參的IDelegate版本
- DELEGATE_TEMPLATE DELEGATE_TEMPLATE_PARAMS
- class MYGUI_I_DELEGATE
- {
- public:
- virtual ~MYGUI_I_DELEGATE() { }
- virtualbool isType( const std::type_info& _type) = 0;
- virtualvoid invoke( DELEGATE_PARAMS ) = 0;
- virtualbool compare( MYGUI_I_DELEGATE DELEGATE_TEMPLATE_ARGS * _delegate) const = 0;
- };
神奇吧,這裡使用的可以說是巨集實現的多型。
在這段程式碼編譯完了之後,將所有巨集都undefine掉,如
- #undef DELEGATE_TEMPLATE
- #undef DELEGATE_TEMPLATE_PARAMS
- #undef DELEGATE_TEMPLATE_ARGS
- #undef MYGUI_I_DELEGATE
再重新定義雙參版本的,如
- #define DELEGATE_TEMPLATE template
- #define DELEGATE_TEMPLATE_PARAMS <typename TP1, typename TP2>
- #define DELEGATE_TEMPLATE_ARGS TP1 p1, TP2 p2
- #define MYGUI_I_DELEGATE IDelegate2
那麼編譯出來的就是雙參的版本了!
使用這種方法就可以將其他的如CStaticDelegate、CMethodDelegate和CMultiDelegate的各種版本都實現了,
而你要做的僅是重新define下那些巨集就行了,夠方便了吧。
下一篇文章將會介紹MyGUI實現的一些輔助類,如單委託和DelegateUnlink。並給出一個測試例子,測試該委託機制對C++各種函式的支援。
1.引言
按上一篇文章的方法,你已經可以使用任意引數的函式委託了。這裡介紹下MyGUI實現的兩個輔助類,CDelegate類和IDelegateUnlink。如果你不為了深入瞭解MyGUI的委託實現,可以跳過此處。CDelegate即為單委託,實際效果跟函式指標差不多,於CMultiDelegate的區別在於其不支援多播。而IDelegateUnlink類主要是在CMultiDelegate中使用,在多播下一次性去掉自身的所有委託。
2.單委託
- // 無參的單委託實現
- class CDelegate
- {
- public:
- typedef CDelegate IDelegate;
- CDelegate () : mDelegate(0) { }
- CDelegate (const CDelegate& _event)
- {
- // 在拷貝構造時,將被拷貝的委託去掉,即委託只存在一份
- mDelegate = _event.mDelegate;
- const_cast<CDelegate&>(_event).mDelegate = 0;
- }
- ~CDelegate () { clear(); }
- bool empty() const { return mDelegate == 0; }
- void clear()
- {
- if (mDelegate)
- {
- delete mDelegate;
- mDelegate = 0;
- }
- }
- CDelegate & operator=(IDelegate* _delegate)
- {
- delete mDelegate;
- mDelegate = _delegate;
- return *this;
- }
- CDelegate & operator=(const CDelegate& _event)
- {
- // 在賦值時,將右值的委託去掉,即委託只存在一份
- delete mDelegate;
- mDelegate = _event.mDelegate;
- const_cast<CDelegate&>(_event).mDelegate = 0;
- return *this;
- }
- void operator()( )
- {
- if (mDelegate == 0) return;
- mDelegate->invoke( );
- }
- private:
- IDelegate * mDelegate;
- };
可以看到,單委託只實現了 = 運算子,沒有實現 += 運算子。
而且在賦值時會將原委託去掉,確保只有一份委託。
其實單委託跟普通函式指標差不多,在使用單委託的地方可以換成使用普通函式指標。
3.斷開委託
- // 斷開委託的基類
- class IDelegateUnlink
- {
- public:
- virtual ~IDelegateUnlink() { }
- IDelegateUnlink() { m_baseDelegateUnlink = this; }
- bool compare(IDelegateUnlink * _unlink) const { return m_baseDelegateUnlink == _unlink->m_baseDelegateUnlink; }
- private:
- IDelegateUnlink * m_baseDelegateUnlink;
- };
所謂斷開委託,只能用在多重委託,即CMultiDelegate中,可以斷開自身與其相連的所有委託。
使用方法就在將自身的類從IDelegateUnlink派生,然後使用CMultiDelegate中的clear函式即可斷開委託。
在下面會有例子說明。
4.測試
- /* 測試Delegate對不同函式的支援
- * 可以參考下不同函式的使用方式
- */
- #include "delegate.h"
- #include <iostream>
- usingnamespace std;
- // 普通函式1
- void func(int a, int b)
- {
- cout << "func(" << a << ", " << b << ")" << endl;
- }
- // 普通函式2
- void func2(int a, int b)
- {
- cout << "func2(" << a << ", " << b << ")" << endl;
- }
- // 普通類
- class NormalClass
- {
- public:
- // 類的普通成員函式
- void normalFunc(int a, int b)
- {
- cout << "NormalClass::normalFunc(" << a << ", " << b << ")" << endl;
- }
- };
- // 實現了IDelegateUnlink的類
- class BaseUnlinkClass : public delegates::IDelegateUnlink
- {
- public:
- // 類的虛擬函式
- virtualvoid virFunc(int a, int b)
- {
- cout << "BaseUnlinkClass::virFunc(" << a << ", " << b << ")" << endl;
- }
- // 類的普通成員函式
- void normalFunc(int a, int b)
- {
- cout << "BaseUnlinkClass::normalFunc(" << a << ", " << b << ")" << endl;
- }
- };
- class DerivedClass : public BaseUnlinkClass
- {
- public:
- // 類的虛擬函式
- virtualvoid virFunc(int a, int b)
- {
- cout << "DerivedClass::virFunc(" << a << ", " << b << ")" << endl;
- }
- // 類的靜態成員函式
- staticvoid staticFunc(int a, int b)
- {
- cout << "DerivedClass::staticFunc(" << a << ", " << b << ")" << endl;
- }
- };
- // 模板函式
- template<class T>
- void TFunc(T a, T b)
- {
- cout << "TFunc(" << a << ", " << b << ")" << endl;
- }
- int main()
- {
- BaseUnlinkClass *baseUnlinkClass = new BaseUnlinkClass;
- DerivedClass *derivedClass = new DerivedClass;
- NormalClass *normalClass = new NormalClass;
- // 定義委託
- typedef delegates::CMultiDelegate2<int, int> EvenetHandler;
- EvenetHandler event;
- // 新增普通函式
- event += newDelegate(func);
- event += newDelegate(func2);
- // 新增類的普通成員函式
- event += newDelegate(normalClass, &NormalClass::normalFunc);
- event += newDelegate(baseUnlinkClass, &BaseUnlinkClass::normalFunc);
- // 新增類的虛擬函式
- event += newDelegate(baseUnlinkClass, &BaseUnlinkClass::virFunc);
- event += newDelegate(derivedClass, &DerivedClass::virFunc);
- // 注意在多型下,使用基類指標時,函式指標要用基類的函式指標,不能用派生類的
- // 但是在呼叫時會響應多型,也就是會呼叫派生類的虛擬函式
- event += newDelegate((BaseUnlinkClass*)derivedClass, &BaseUnlinkClass::virFunc);
- // 新增類的靜態成員函式
- event += newDelegate(&DerivedClass::staticFunc);
- // 新增模板函式
- event += newDelegate(TFunc<int>);
- // 觸發事件
- event(1, 2);
- cout << endl;
- // 去掉函式
- event -= newDelegate(func);
- // 去掉baseUnlinkClass所有的函式
- event.clear(baseUnlinkClass);
- // 去掉derivedClass所有的函式
- // 注意靜態成員函式staticFunc不會去掉
- event.clear(derivedClass);
- //event.clear(normalClass);
- // 錯誤呼叫,normalClass不是IDelegateUnlink的派生類
- // 不能使用clear去掉自身的函式
- // 應該使用如下方法
- event -= newDelegate(normalClass, &NormalClass::normalFunc);
- // 觸發事件
- event(2, 3);
- cout << endl;
- return 0;
- }
相關推薦
C++實現委託機制(一)
1.引言: 如果你接觸過C#,你就會覺得C#中的delegate(委託)十分靈巧,它的用法上和C\C++的函式指標很像,但是卻又比C\C++的函式指標更加靈活。並且委託可以一對多,也就是可以註冊多個函式,甚至是某個類的非靜態成員函式。而實現事件訊息
C++實現 反射 機制( 即根據 類名 建立 類例項)Create C++ Object Dynamically
Create C++ Object Dynamically Introduction C++不像C#和Java那樣具有反射的能力,通常不能根據任意一個class name來建立該class的instance。但我們知道在MFC中,任何繼承了CObject的類都可以根據其名字來建立例項,它是使用了一些巨集。而
【Unity基於C#事件委託機制,最輕鬆易懂的版本,一個例項解決你的困惑】
PS:題主涉世尚淺,如有不對的地方還請大佬指出~ 對於C#的委託和事件機制,看似複雜抽象,但其邏輯條理十分清晰,所以理解起來也不會太難,關鍵在於瞭解它兩的聯絡,以及工作原理。 委託 觀察者模式: 定義了物件之間的一對多依賴,這樣一來,當一個物件改變狀態時
C++實現的委託機制
1.引言 下面的委託實現使用的MyGUI裡面的委託實現,MyGUI是一款強大的GUI庫,想理解更多的MyGUI資訊,猛擊這裡http://mygui.info/ 最終的程式碼可以在這裡下載:http://download.csdn.net/detail/gouki04/3
C#使用委託和事件實現釋出訂閱者模式
事件是C#中的高階概念,和js中的滑鼠點選$("tag").click,懸停$("tag").hover或css元素樣式的改變(onChanged)等事件,當事件觸發才執行我們所委託的方法。 步驟: 1、建立一個委託; 2、將建立的委託與特定事件關聯; 3、編寫C#事件處理程式; 4、利用編
C#實現軟體授權,限定MAC執行(軟體license管理,簡單軟體註冊機制)
最近做了一個綠色免安裝軟體,領導臨時要求加個註冊機制,不能讓現場工程師隨意複製。事出突然,只能在現場開發(離開現場軟體就不受我們控了)。花了不到兩個小時實現了簡單的註冊機制,稍作整理。 基本原理:1.軟體一執行就把計算機的CPU、主機板、BIOS、MAC地址記錄下來,然後加密(key=key1)生成
C#委託機制筆記
首先要明確委託機制 根據查閱的資料描述,委託相當於C語言的指標,函式指標代表函式在flash中的地址,入口。 但是委託是面向物件的型別安全,具有保障,故而需要一些繁瑣的定義,宣告,例項之後才可以使用,使用時作為引數傳遞,是引用傳遞。 委託的例項化中的引數,即委託的方法既可以
C++實現反射(即類似於.NET、java的反射機制)
NET下的很多技術都是基於反射機制來實現的,反射讓.NET平臺下的語言變得得心應手。最簡單的,比如列舉型別,我們我可以很容易的獲得一個列舉變數的數值以及其名稱字串。 可是,在C++中,列舉變數本質上和一個整形變數沒有區別,我們很難獲取一個列舉變數的名稱字串。 其實在C++中,我們可以通過巨集
c++ 帶引數的巨集定義實現反射機制
lua 這種指令碼語言用久了,總覺得反射機制就應該理所當然的嵌入在語言特性裡。 比如希望根據自己傳的型別名變數,動態去 new 一些例項。在 lua ,js 裡做起來就非常簡單,然而在 c++裡面做起來,就需要稍微費些周折。 好在 c++ 巨集定義 支援傳入引數
Unity3D 利用C#實現簡單的代理模式Delegate(委託)
Ref: http://www.cnblogs.com/shadow7/p/5892641.html 1、Delegate是什麼? Delegate中文翻譯為“委託”。 C#語言是支援代理的,
c與c++相互呼叫機制分析與實現
c++通常被稱為Better c,多數是因為c++程式可以很簡單的呼叫c函式,語法上基本實現相容。最常用的呼叫方式就是c++模組呼叫c實現的dll匯出函式,很簡單的用法,使用extern "C"將c標頭檔案或者函式修飾下。 本文主要涉及到在c模組中如何呼叫c++函式,或者換個名字,extern
c++函式過載機制實現原理
一、c++函式過載的定義: 在同一作用域類,一組函式的函式名相同,引數列表不同(引數個數不同/引數型別不同),返回值可同可不同 二、函式過載的作用: 過載函式通常用來在同一個作用域內 用同一個函式名 命名一組功能相似的函式,這樣做減少了函式名的數量,避
C# 使用委託實現非同步程式設計的四種方式
一、關於委託 1、委託概念:委託是一個類,它定義了方法的型別,使得可以將方法當作另一個方法的引數來進行傳遞 個人角色這個概念有些晦澀難懂,大家可以把委託當成一個方法的指標就好了,可以指向一個方法。或者通過(+=)的方式指向多個。 2、四種宣告方式 1)直接用del
C# 使用委託實現多執行緒呼叫窗體的四種方式
1、方法一:使用執行緒 功能描述:在用c#做WinFrom開發的過程中。我們經常需要用到進度條(ProgressBar)用於顯示進度資訊。這時候我們可能就需要用到多執行緒,如果不採用多執行緒控制進度條,視窗很容易假死(無法適時看到進度資訊)。下面
c#使用委託實現辛普森法求多個函式的定積分
用辛普生法對幾個不同的被積函式求指定區間的定積分。被積函式為f(x),積分割槽間[a,b]被等分為n=2k份,每份步長為h=(b-a)/n,則積分值為:S≈h((f(a)+f(b))/2 +f(a+h)+…+f(a+(n-1)h))。 執行結果:
c# 用委託和事件實現不同窗體間的通訊(一)
C# 中的“事件”是當物件滿足一定條件,發生某些事情時,類向該類的客戶提供通知的一種方法。使用事件,擁有該事件的物件不必知道需要通知誰,一旦滿足了某個條件,將自動呼叫該事件,正確通知每個需要通知的物件。通過使用事件,提高了程式的模組化程度。 例子:通過form1開啟f
利用Objective-C的反射機制和執行時特性實現類靜態方法的動態訪問(一)
如題,灑家今天在搭建蘋果手機APP開發框架中遇到一個坑爹問題,折騰了半天,總算研究出來了,特記錄如下: 1、先說具體需求,本人實現了一個自定義檢視控制元件,通過KVC特性先從plist配置檔案中讀取資料,轉換成模型物件,然後根據模型物件動態建立檢視物件,這時就需要用到Obj
用C++實現簡單的反射機制
備忘記錄下來。 程式碼如下: 巨集定義REGISTER解讀: 這個巨集做了兩件事情, 第一件事情是聲明瞭一個函式,即 className* objectCreator##classNam
實現C++ 列舉反射機制
上一階段寫了一些功能需要列舉反射機制,但是C++不支援,很無奈。最近又遇到這個問題,所以自己實現了一版, 自己的版本 列舉定義是 巨集定義,其他的都是一些解析 程式碼如下: 第一次貼程式碼,也不太會 //enum_map.h標頭檔案 </pre><p&g
C++ 模仿Android實現Handler機制
前言: 一直使用android的Handler,感覺非常好用,但是當我使用C++程式設計時,想使用Android Handler一樣的程式設計模式,竟不知如何下手,網上找了很久,都沒找到具體的實現,能搜尋到MFC中使用handler,但是一直不搞windows的