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

flipcode
仿函數(shù)、綁定、橋接、委托相關(guān)討論:
以下隨便討論下,沒(méi)突出的中心論點(diǎn),個(gè)中理論只代表我個(gè)人觀點(diǎn),難免有錯(cuò):),歡迎指正。
一。需求:
在事件處理常常會(huì)碰到這樣的情況:
1。接口分離。即invokers(調(diào)用者)與(receivers)接收者分離。
2。時(shí)間分離。

比如說(shuō):UI相關(guān)元素(按鈕、菜單等)就是一個(gè)invokers。
receivers則是響應(yīng)命令的對(duì)象(如對(duì)話框或應(yīng)用程序本身)。
這需要我們要先將UI相關(guān)元素的事件響應(yīng)的接收者在初始化時(shí)先保存起來(lái)。
待后用戶按下按鈕等再觸發(fā)(即invokers通過(guò)調(diào)用對(duì)應(yīng)先前保存的receivers來(lái)執(zhí)行命令)
嗯,在delphi、java、vcl、.net中有相關(guān)的實(shí)現(xiàn)。而vc則需要自己來(lái)弄。

二。仿函數(shù)的實(shí)現(xiàn):
在說(shuō)仿函數(shù)前先說(shuō)說(shuō)我們應(yīng)該怎么保存這些操作相關(guān)函數(shù)的呢?
// 一般的函數(shù)我們可以這么存:
void (*fun)() = Test;
(*fun)();
// 而類成員函數(shù)可以這么做:
void (CTest::*mfn)(); // 或用 typedef void (CTest::*MFN_TEST)(); MFN_TEST mfn;
mfn = CTest::Test;
CTest a, *p=new CTest;
(a.*mfn)(); // 調(diào)用方法1
(p->*mfn)(); // 調(diào)用方法2
如上所述可見(jiàn)為了處理前面所述的事件響應(yīng)情況,我們通常會(huì)用回調(diào)函數(shù),
就是把類成員函數(shù)定義為靜態(tài)函數(shù),在初始時(shí)保存函數(shù)地址(與一般函數(shù)處理類同)及對(duì)應(yīng)的對(duì)象指針,
在事件觸發(fā)時(shí)調(diào)用對(duì)應(yīng)的靜態(tài)函數(shù),而該函數(shù)中在把指針強(qiáng)制轉(zhuǎn)化為對(duì)應(yīng)類型對(duì)象地址,
得以操縱該對(duì)象的成員變量(嗯,理論上跟成員函數(shù)的實(shí)現(xiàn)差不多,成員函數(shù)會(huì)由編譯器安插一個(gè)
this指針作為第1個(gè)參數(shù)傳給函數(shù),以便可以操作該this對(duì)象的成員)。

回調(diào)函數(shù)應(yīng)用的具體代碼如下:
1). 回調(diào)接口(靜態(tài)函數(shù)法):
//======================================================
#include "stdafx.h"
#include

typedef void(*KEY_RESPOND)(void* /*,param*/);
struct CListener
{
void* pThis;
KEY_RESPOND pfn;
CListener() : pThis(0), pfn(0){}
};
class CInput
{
std::list m_listListener;
public:
void AddListener( CListener* pListener ){
m_listListener.push_back( pListener );
}
void RemoveListerner( CListener* pListener ){
std::list::iterator iter;
for( iter = m_listListener.begin(); iter!= m_listListener.end();iter++ ){
if( pListener == (*iter) ){
m_listListener.erase( iter ); break;
}
}
}
void HitOneKey(){
std::list::iterator iter;
for( iter = m_listListener.begin(); iter!= m_listListener.end();iter++ ){
if( (*iter)->pfn && (*iter)->pThis ){
(*(*iter)->pfn)( (*iter)->pThis );
}
}
}
void clearListener(){
m_listListener.clear();
}
};
class CUI
{
public:
static void InputProc(void* pThis/*,param*/){
__asm int 3 // 下個(gè)斷點(diǎn)測(cè)試下(某些編譯器不能這么寫(xiě),vc可以)
}
};

CUI ui;
CInput input;
int _tmain(int argc, _TCHAR* argv[])
{
// 初始:
CListener* pListener = new CListener;
pListener->pfn = &CUI::InputProc;
pListener->pThis = &ui;
// 觸發(fā):
input.AddListener( pListener ); // input即為invokers(調(diào)用者,但叫觸發(fā)者好點(diǎn))
input.HitOneKey(); // 某處事件觸發(fā),內(nèi)部呼叫receivers(這里是原先保存的CUI對(duì)象)來(lái)真正處理該事件(InputProc(...)方法)。
// 清除
input.clearListener();
if( pListener )
{
delete pListener;
pListener = NULL;
}
return 0;
}
//======================================================

// 第2種方法: 回調(diào)類(虛函數(shù)多態(tài)法):
//======================================================
class IWillBack
{
public:
virtual void InputProc(/*參數(shù)略...*/){}
};
class CInput
{
public:
void RegisterListener(IWillBack* pListener){
m_pListener = pListener; // 這里用list存起來(lái)才好,這里只作測(cè)試
}
void OnInputEvent(){
m_pListener->InputProc(/*參數(shù)略...*/);
}

private:
IWillBack* m_pListener;
};
class CUI : public IWillBack
{
public:
void InputProc(/*參數(shù)略...*/){ /*..實(shí)際處理代碼..*/}
private:
};

int _tmain(int argc, _TCHAR* argv[])
{
CInput aa;
CUI bb;
aa.RegisterListener(&bb);
aa.OnInputEvent();
return 0;
}
//======================================================

但是第1種靜態(tài)函數(shù)用法是不直觀的,第2種需要派生增加了之間的聯(lián)系,而為了方便我們通常會(huì)將成員函數(shù)指針轉(zhuǎn)化為函數(shù)對(duì)象來(lái)處理,即仿函數(shù)(一般是指重載了()操作符的類)來(lái)實(shí)現(xiàn)。

類似于這樣的操作,stl提供了mem_fun、mem_fun_ref、binder1st、binder2nd簡(jiǎn)單操作。
但stl的方法相對(duì)比較原始而受限制,比如說(shuō)std::mem_fun需要成員函數(shù)有返回值,
std::mem_fun最多只能支持成員函數(shù)有一個(gè)參數(shù)等,
下面來(lái)看std:mem_fun_ref不支持成員函數(shù)返回值為void的一個(gè)例子:
//======================================================
#include
class CFoo
{
public:
void test() // 只有將void改成別的類型才可以,如:int
{
return 0;
}
};
void main()
{
CFoo t;
std::mem_fun_ref(&CFoo::test)(t);
}
//======================================================
上述代碼只有將void改成別的類型(如int)才可以,
那么為什么不可以處理返回void的函數(shù)呢? stl的實(shí)現(xiàn)究竟是怎么樣的呢?
嗯,stl簡(jiǎn)單實(shí)現(xiàn)了mem_fun_ref及mem_fun,其中mem_fun_ref以引用方式處理函數(shù)所屬對(duì)象,
而mem_fun以指針?lè)绞教幚砗瘮?shù)所屬對(duì)象。
現(xiàn)在讓我們從vc的stl挖出部份代碼來(lái)看看,

1.stl的實(shí)現(xiàn):
以mem_fun_ref為例(省略某些對(duì)說(shuō)明不重要的細(xì)節(jié),兩條虛線包括的代碼為stl類似源碼):
//======================================================
//----------------------------------------------------------
namespace stl_test
{
// 主要實(shí)現(xiàn):
template
class mem_fun_ref_t
{
public:
mem_fun_ref_t( R (T::*_Pm)() ) : _Ptr(_Pm) {} // 構(gòu)造: 保存成員函數(shù)地址
R operator()(T& _X) const // 調(diào)用: 這里可看出mem_fun_ref以引用方式處理
{
return ((_X.*_Ptr)()); // 這里執(zhí)行調(diào)用函數(shù),并返回該函數(shù)所返回值
}
private:
R (T::*_Ptr)(); // 指向成員函數(shù)地址的指針
};
// 這里只是利用函數(shù)的參數(shù)推導(dǎo)來(lái)自動(dòng)獲取型別(方便調(diào)用)
template inline
mem_fun_ref_t mem_fun_ref(R (T::*_Pm)())
{
return (mem_fun_ref_t(_Pm));
}

} // end of namespace test_stl
//----------------------------------------------------------
class CFoo
{
public:
int test1(){
__asm int 3
return 0;
}
void test2(){
__asm int 3
}
};
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
CFoo t;
stl_test::mem_fun_ref( &CFoo::test1 ) (t);
return 0;
}
//======================================================
/////////////////////////////////////////////////////////////////
從源碼"return ((_X.*_Ptr)()); " 可以看到stl直接返回該函數(shù)所返回值。
所以函數(shù)沒(méi)有返回值(即為void時(shí))的話編譯器就會(huì)報(bào)錯(cuò)。好,那么如果我們?cè)?br>這里只是直接執(zhí)行函數(shù)而不用return返回的話編譯器應(yīng)該可以通過(guò)了。

嗯,boost中正是這么處理的。(btw.為了更為通用,boost對(duì)stl原有仿函數(shù)及綁定作了大量的改進(jìn)工作)。
但是具體應(yīng)該怎么區(qū)分有沒(méi)有返回值呢?這個(gè)也容易,我們只需用到模板的偏特性就可
以做到。下面就看看boost的實(shí)現(xiàn)(btw.boost有兩種版本,我用的是兼容版本,代碼難看)

2. boost的實(shí)現(xiàn)(這里我把boost的一大堆宏(真@$@#@#難看,loki在這方面來(lái)得比較清爽)去掉了):
/////////////////////////////////////////////////////////////////
// notreturn.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
//------------------------------------
namespace boost_test
{
template // 有返回值時(shí)會(huì)調(diào)用這個(gè)
struct mf
{
template
class inner_mf0
{
R (T::*_Ptr)();
public:
inner_mf0(R (T::*f)()) : _Ptr(f) {}
R operator()(T& X) const
{
return ((X.*_Ptr)());
}
};
};
template<> // 沒(méi)有反回值時(shí)會(huì)調(diào)用這個(gè)
struct mf // 偏特化
{
template
class inner_mf0
{
R (T::*_Ptr)();
public:
inner_mf0(R (T::*f)()) : _Ptr(f) {}
R operator()(T& X) const
{
((X.*_Ptr)());
}
};
};
// 創(chuàng)建一派生類,派生于上述基類
template
struct mf0 : public mf::inner_mf0
{
typedef R(T::*F)();
explicit mf0(F f) : mf::inner_mf0(f) {}
};
// 通過(guò)函數(shù)的參數(shù)推導(dǎo)自動(dòng)獲取類型
template
mf0 mem_fn( R(T::*f)() )
{
return mf0(f);
}
} // namespace boost_test
//------------------------------------

class CFoo
{
public:
int test1(){ return 0; }
void test2(){}
};
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
CFoo t;
boost_test::mem_fn( &CFoo::test1 ) (t);
return 0;
}
/////////////////////////////////////////////////////////////////

從上述代碼可以看到偏特性幫助我們解決了返回值為void的情況。但是手寫(xiě)了兩份
基本相同的代碼。。。
另外處理參數(shù)個(gè)數(shù)的情況也很容易,只要分別實(shí)現(xiàn)不同參數(shù)的各個(gè)模板類就可以了,
boost最多只能支持成員函數(shù)有8個(gè)參數(shù),因?yàn)樗鼉?nèi)部實(shí)現(xiàn)了8份這樣不同參數(shù)模板類。
其實(shí)的處理方法都是一模一樣的,可是由于語(yǔ)言的限制我們還是沒(méi)有辦法不一一實(shí)現(xiàn)
不同參數(shù)的類:。在loki中參數(shù)可以用TList實(shí)現(xiàn)任意的參數(shù),但是在實(shí)現(xiàn)還是得老
老實(shí)實(shí)的每份手寫(xiě)一份(loki實(shí)現(xiàn)了15份可以支持15個(gè)參數(shù))。
這真讓人郁悶。。。不過(guò)沒(méi)辦法。

說(shuō)完來(lái)仿函數(shù),下面開(kāi)始說(shuō)說(shuō)有關(guān)綁定,stl、boost、loki的綁定的意思是
對(duì)某物實(shí)體的“綁定”,通俗來(lái)說(shuō)是指對(duì)函數(shù)、構(gòu)造函數(shù)、仿函數(shù)等與其對(duì)應(yīng)的某個(gè)參數(shù)的綁定,
以便在調(diào)用時(shí)不用再次輸入此參數(shù)(因?yàn)槟承r(shí)候參數(shù)是固定的,比如說(shuō)綁定一個(gè)內(nèi)部存有
成員函數(shù)地址的仿函數(shù)和它對(duì)應(yīng)的對(duì)象地址在一起)。
以下是stl的bind用法:
//================================
#include "stdafx.h"
#include // stl
#include // boost

struct CFoo {
int test(int){
return 0;
}
};
void main()
{
boost::function1 f; // 這里用了boost
CFoo obj;
f = std::bind1st(std::mem_fun(&CFoo::test), &obj);
f(5);
}
//================================
loki中的BindFirst比較類似于stl的binder
(binder1st,binder2nd),但是它是通用的,可以通過(guò)嵌套實(shí)現(xiàn)任意多個(gè)參數(shù)綁定:
//================================
void f()
{
Functor cmd1(something);
Functor cmd2(BindFirst(cmd1, 10));
cmd2(20);
Functor cmd3(BindFirst(cmd2, 30));
cmd3();
}

而boost中的實(shí)現(xiàn)是以占位符來(lái)表現(xiàn),具體如何實(shí)現(xiàn),下回繼續(xù)討論(嗯,
boost代碼的宏太多了,這部份還是等有空再補(bǔ)全了,現(xiàn)在我們來(lái)看看如何實(shí)現(xiàn)一個(gè)委托類)

三。委托類的實(shí)現(xiàn):
1. 橋接模式:
設(shè)計(jì)模式告訴我們可以使用橋接模式(Bridge Pattern)減少對(duì)象之間的 耦合度,橋接模式如下:
Invoker <>------------------->* Interface
^
|
Receiver
上圖的Invoker表示事件觸發(fā)者,Receiver表示事件處理者,符號(hào)類似于<c++大規(guī)模編程。。>一書(shū)所描述(注:這里符號(hào)對(duì)位可能出錯(cuò):變成左對(duì)齊了),
其中<>------------------->表示Invoker 內(nèi)含(擁用)Interface(即Invoker 有Interface的變量或指針并負(fù)責(zé)Interface的釋放),
而*號(hào)表示可有多個(gè)。
^
|  號(hào)則表示繼承于(Receiver繼承于Interface)。

好,我們先來(lái)分析前面在" 第2種方法: 回調(diào)類(虛函數(shù)多態(tài)法):"的實(shí)現(xiàn)思想(請(qǐng)回到前面看看代碼),
它其實(shí)就是一個(gè)橋接模式,如下(括號(hào)內(nèi)對(duì)應(yīng)前面所實(shí)現(xiàn)的類):
Invoker(CInput) <>--------------->* Interface(IWillBack)
^
|
Receiver(CUI)
對(duì)照我們前面實(shí)現(xiàn)的代碼可以發(fā)現(xiàn)此種實(shí)現(xiàn)的橋接的缺點(diǎn)是:每一個(gè)想要
注冊(cè)一方法到Invoker中以便Invoker在事件觸發(fā)時(shí)調(diào)用的類(如Receiver)都要派生自Interface。
有沒(méi)有更好的辦法再次減少這種耦合度呢?這正是下面我們要討
論的下一種設(shè)計(jì)模式:
2. 委托與事件:
委托的處理設(shè)計(jì)如下:
Invoker <>--------------------->* Interface
^
|
Implementation -----------------> Receiver
即在原橋接模式下再加一層間接性:Implementation 。其中
Implementation與Receiver之間的----------------->表示Implementation引用了Receiver一些服務(wù),
即Implementation用到了Receiver某些東西(如函數(shù)或數(shù)據(jù))。嗯,這些解釋不知是否適當(dāng),希望不會(huì)誤導(dǎo)。。。
好,一開(kāi)始可能我們會(huì)這么設(shè)計(jì):
//======================================================================================
class handle {};
template
class Implementation : public handle
{
T* m_pThis;
public:
Implementation ( T* pThis ) : m_pThis(pThis) {}
template
void execute( void (T::*mfn)(T1), T1 arg ) { (m_pThis->*mfn)( arg ); }

};
struct Receive {
void Proc(int) {
__asm int 3
}
};
Receive a;
void Invoker(){
Implementation test = Implementation (&a);
test.execute( Receive::Proc, 10 ); // 當(dāng)事件發(fā)生時(shí)調(diào)用
};
int _tmain(int argc, _TCHAR* argv[])
{
Invoker();
}
//======================================================================================
但是Invoker知道了太多Receive的信息,況且我們想讓觸發(fā)者Invoker作成一個(gè)類。
一個(gè)改進(jìn)的版本如下:
//-------------------------------------------------------------
// signal slot system
// 注: 該法我是看了"落木隨風(fēng)"的"委托、信號(hào)和消息反饋的模板實(shí)現(xiàn)技術(shù)",
// 代碼作了部份添加。在這里非常的感謝他!
// 他的博客:http://blogs.gcomputing.com/rocwood/archives/000154.html
//-------------------------------------------------------------
// Delegation.cpp : Defines the entry point for the console application.
//
#include

#ifndef K_DELEGATE_H
#define K_DELEGATE_H

namespace kUTIL
{
// 1. 橋接類(純虛類):
// 為什么叫作橋接?
// 因?yàn)橥ㄟ^(guò)它的虛函數(shù)方法可以調(diào)用到對(duì)應(yīng)的正確的不同派生實(shí)例(指后面
// 提到的委托人)所改寫(xiě)的虛函數(shù)方法(這是委托人用來(lái)完成委托任務(wù)的方法)
struct kDelegationInterface
{
virtual ~kDelegationInterface() {};
virtual void Execute() = 0;
};
// 2. 委托類(派生于橋接類,這里我叫為”委托人“)
// 為什么叫委托?
// 因?yàn)檎{(diào)用者把“通知”的工作委托給它來(lái)負(fù)責(zé)處理。
// 一個(gè)“委托人”保存了: a.”接收者“(對(duì)象指針m_pThis) 及 b.“要作的事”(方法指針m_mfn),
// 以便調(diào)用者發(fā)出信號(hào)彈(后面提到,信號(hào)彈有一個(gè)作橋接用的純虛類的指針指向相應(yīng)的委托人)
// 告知此信號(hào)對(duì)應(yīng)的委托人來(lái)完成它被委托的工作:即讓“接收者”(m_pThis)作”要作的事“(m_mfn)。
template
struct kDelegationImpl : public kDelegationInterface
{
typedef void ( T::* MFN )();
kDelegationImpl( T* pthis, MFN mfn ) : m_pThis( pthis ), m_mfn( mfn ) {
}
virtual void Execute() {
if( m_pThis ) {
( m_pThis->*m_mfn )();
}
}
T* m_pThis;
MFN m_mfn;
};

// 3. 信號(hào)彈(實(shí)現(xiàn)為仿函數(shù)來(lái)調(diào)用統(tǒng)一的虛函數(shù)接口):
// 為什么叫信號(hào)?
// 因?yàn)楫?dāng)"信號(hào)彈"發(fā)射時(shí)(調(diào)用信號(hào)的操作符"()")
// 它會(huì)通知所指向的"委托人"事件發(fā)生了(調(diào)用純虛類指針的m_DI->Execute()方法)。
// 一個(gè)信號(hào)保存了一個(gè)指向?qū)?yīng)”委托人“的橋接類(純虛類)指針。
struct kSignal0
{
kDelegationInterface* m_DI; // 純虛類的指針
kSignal0() : m_DI(0) {}
// 1. 純虛類的m_DI指針可以指向不同的派生實(shí)例:
template
void ConnectSlot(T* recv, void (T::* mfn)()) {
DisConnect();
m_DI = new kDelegationImpl( recv, mfn );
int test = 0;
}
void DisConnect() {
if( m_DI ) { delete m_DI; m_DI = NULL; }
}
// 2. 用統(tǒng)一的純虛類指針調(diào)用不同派生類改寫(xiě)的虛函數(shù)
void operator() () {
if( m_DI ) {
m_DI->Execute();
}
}
};

// 下面是兩個(gè)為方便使用的函數(shù):
template
void kConnect( kSignal0& sgn, T* pObj, void(T::*fn)())
{
sgn.ConnectSlot( pObj, fn );
int i = 0;
}
inline void kDisConnect( kSignal0& sgn )
{
sgn.DisConnect();
}
} // end of namespace kUTIL
#endif //#ifndef K_DELEGATE_H

//----------------------------------------------------------------------------
// 一個(gè)使用實(shí)例:
class kButton {
public:
kUTIL::kSignal0 sgnMouseBtnUp;
void OnMouseButtonUp() { sgnMouseBtnUp(); }
};

class kDialog {
kButton btn;
public:
kDialog() {
kUTIL::kConnect( btn.sgnMouseBtnUp, this, &kDialog::DoWork ); // vc6下這里kDialog::DoWork的前面一定要可加"&"號(hào)
}
void DoWork() {
__asm int 3
}
void TestMouseHit() { btn.OnMouseButtonUp(); }
};

int main(int argc, char* argv[])
{
kDialog dlg;
kButton btn;
kUTIL::kConnect( btn.sgnMouseBtnUp, &dlg, kDialog::DoWork ); // vc6下這里kDialog::DoWork的前面可加/不加"&"號(hào)

// 測(cè)試一:
btn.OnMouseButtonUp();

// 測(cè)試二:
dlg.TestMouseHit();
return 0;
}

// 委托實(shí)例總結(jié):
// 下面我們來(lái)具體說(shuō)明”當(dāng)某事發(fā)生時(shí),調(diào)用者發(fā)射信號(hào)彈通知對(duì)應(yīng)的接收者作相應(yīng)處理“
// 1. "調(diào)用者" 擁有各種信號(hào)彈。
// 2. 初始時(shí),我們把信號(hào)彈與對(duì)應(yīng)的委托人聯(lián)系起來(lái),并讓委托人記錄在信號(hào)觸發(fā)時(shí)應(yīng)該通知的"接收人"和"接收人該作的事"。
// a. 信號(hào)彈保存了橋(純虛類)指針,指針指向通過(guò)其模板函數(shù)ConnectSlot方法來(lái)找出(產(chǎn)生的)委托人(委托實(shí)例)。
// b. 委托人(委托實(shí)例)在信號(hào)彈用ConnectSlot方法產(chǎn)生它的時(shí)候保存了函數(shù)ConnectSlot所傳入的兩個(gè)參數(shù):
// 即"接收者指針"及"其方法指針"。
// 3. 當(dāng)事件發(fā)生時(shí)"調(diào)用者"發(fā)射對(duì)應(yīng)信號(hào)彈后,信號(hào)彈會(huì)調(diào)用其所保存的純虛類指針的虛函數(shù)方法,
// 于是由于虛函數(shù)特性就會(huì)調(diào)用到其所指向的委托實(shí)例(委托人)所改寫(xiě)的方法。
// 5. 委托人改寫(xiě)的方法中通過(guò)其所保存的”接收者指針“及其"方法指針"來(lái)呼叫"接收者"用對(duì)應(yīng)的”方法指針“
// 來(lái)處理事情。
// 即如下流程:
// "調(diào)用者"發(fā)射"信號(hào)彈" ---> "信號(hào)彈"通過(guò)"橋"找到對(duì)應(yīng)"委托人" ---> "委托人"呼叫"接收者"作"該作的事"

//=============================================================================
嗯,這樣到此,一個(gè)非常方便的委托類就得以實(shí)現(xiàn)了!如果你還不懂的話請(qǐng)仔細(xì)的琢磨,如此精華(因?yàn)楹?jiǎn)單而強(qiáng)大)
不要錯(cuò)過(guò)。不過(guò)上述只是部份實(shí)現(xiàn),當(dāng)你要支持帶參數(shù)及返回值的各種情況的話,還得自己作擴(kuò)充。
返回值的處理方法可參見(jiàn)前面剖述boost的mem_fn的處理方法,而帶不同參數(shù)的處理則只能一一手動(dòng)
實(shí)現(xiàn),就象前面所說(shuō)的那樣,這是很無(wú)奈的事情,但是目前來(lái)說(shuō)沒(méi)有辦法。。。

(待續(xù)。。。。。。,如果有時(shí)間有必要的話。。。)

附:
loki下載:
http://sourceforge.net/projects/loki-lib/

boost下載:
http://sourceforge.net/projects/boost/

2004.10.26更新:
修正:
原void connect( Signal0& sgn,T1 obj, void(T2::*fn)())改成
void connect( Signal0& sgn,T1& obj, void(T2::*fn)())
另外加了kDisConnect釋放內(nèi)存,原來(lái)只作測(cè)試沒(méi)寫(xiě)它,現(xiàn)在還是加上了。

--------------------------------------------------------------------------------

千里馬肝
實(shí)在是太好了

PS,陽(yáng)春的東西,就會(huì)曲高合寡。 :D

--------------------------------------------------------------------------------

flipcode
好久沒(méi)上網(wǎng)了,
今天上來(lái)看到版主的夸獎(jiǎng),
雖然是過(guò)獎(jiǎng)了,不過(guò)還是感覺(jué)輕飄飄的。。。嘿嘿~~~, :D

--------------------------------------------------------------------------------

kane
嗯,這種技巧是比較實(shí)用的。

posts - 94, comments - 138, trackbacks - 0, articles - 94

Copyright © RichardHe

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            久久性天堂网| 亚洲第一精品夜夜躁人人躁| 欧美在线一二三区| 亚洲在线视频| 欧美一区二区三区播放老司机| 欧美在线网站| 亚洲综合首页| 欧美诱惑福利视频| 亚洲视频在线观看网站| 一区二区成人精品| 亚洲欧美在线aaa| 久久免费午夜影院| 欧美激情精品久久久六区热门| 欧美剧在线观看| 国产麻豆午夜三级精品| 国内一区二区在线视频观看| 91久久精品久久国产性色也91| 中文欧美在线视频| 久久久久久亚洲综合影院红桃 | 午夜精品免费在线| 久久久久久九九九九| 欧美精品 日韩| 国产一区二区电影在线观看| 欧美大片免费| 免费看的黄色欧美网站| 欧美成人性网| 夜夜嗨av一区二区三区网站四季av | 欧美大胆a视频| 国产欧美日韩另类视频免费观看| 一区二区三区在线观看国产| 亚洲综合日本| 亚洲大片在线| 香蕉av777xxx色综合一区| 欧美大胆成人| 欧美午夜不卡影院在线观看完整版免费 | 欧美日韩国产免费| 国产精品日产欧美久久久久| 亚洲精品在线电影| 亚洲一区二区四区| 欧美精品国产一区二区| 影音先锋久久资源网| 亚洲男女自偷自拍| 亚洲精品视频在线观看免费| 久久久夜夜夜| 国模套图日韩精品一区二区| 亚洲欧美精品在线观看| 亚洲精品一区二区三区福利| 久久网站免费| 在线看国产日韩| 久久天天狠狠| 欧美在线三区| 国内精品伊人久久久久av一坑| 性久久久久久久久| 夜夜躁日日躁狠狠久久88av| 欧美韩国在线| 亚洲免费观看高清完整版在线观看熊 | 亚洲国产精品va在线观看黑人| 欧美亚洲一区在线| 亚洲一区二区免费看| 国产精品久久久久毛片软件| aaa亚洲精品一二三区| 亚洲丰满少妇videoshd| 午夜电影亚洲| 亚洲一区亚洲二区| 国产乱理伦片在线观看夜一区| 亚洲欧美精品一区| 午夜电影亚洲| 黄色一区二区三区四区| 欧美大片国产精品| 欧美高清视频| 一区二区三区**美女毛片| 99这里只有久久精品视频| 欧美三级电影一区| 欧美呦呦网站| 久久久久久有精品国产| 亚洲国产综合91精品麻豆| 亚洲国产成人av| 欧美午夜精品电影| 欧美专区在线播放| 久久―日本道色综合久久| 最新中文字幕亚洲| 一区电影在线观看| 国产日韩三区| 欧美sm极限捆绑bd| 欧美日韩一区免费| 久久久蜜桃精品| 欧美不卡福利| 香蕉精品999视频一区二区 | 欧美私人网站| 久久岛国电影| 欧美成人精品一区| 午夜影视日本亚洲欧洲精品| 久久国内精品自在自线400部| 欧美在线视频一区二区| 国产在线观看一区| 亚洲第一区中文99精品| 欧美亚州一区二区三区| 午夜视频久久久久久| 久久国产一区二区三区| 亚洲欧洲精品一区二区三区| 99精品视频免费观看| 国产精品一区二区黑丝| 欧美福利视频在线| 国产精品女主播| 亚洲电影免费| 国产深夜精品| 日韩小视频在线观看专区| 国产夜色精品一区二区av| 亚洲黄色影院| 国产日韩一级二级三级| 91久久精品一区二区三区| 国产色综合久久| 日韩网站在线观看| 亚洲国产一区二区a毛片| 午夜视频精品| 亚洲免费网址| 欧美国产日韩免费| 免费成人在线观看视频| 国产一区二区三区精品久久久| 亚洲美女视频在线观看| 曰韩精品一区二区| 欧美亚洲视频在线观看| 亚洲女性喷水在线观看一区| 欧美xart系列高清| 欧美成va人片在线观看| 国产一区二区毛片| 午夜精品99久久免费| 亚洲综合不卡| 欧美新色视频| 99视频在线观看一区三区| av不卡在线观看| 欧美精品色网| 亚洲精品美女在线观看播放| 亚洲人成在线观看网站高清| 久久一区欧美| 嫩草伊人久久精品少妇av杨幂| 国产午夜精品美女视频明星a级| 亚洲一区三区电影在线观看| 黄色成人av在线| 夜夜嗨一区二区| 亚洲区国产区| 美女视频黄免费的久久| 麻豆精品传媒视频| 一区二区三区亚洲| 久热国产精品视频| 欧美黄色免费网站| 亚洲人妖在线| 欧美aⅴ一区二区三区视频| 欧美激情亚洲自拍| 最新国产精品拍自在线播放| 欧美精品久久99| 日韩亚洲在线观看| 亚洲欧美影音先锋| 国产欧美一区二区三区在线老狼| 亚洲免费一区二区| 久久久人成影片一区二区三区观看| 狠狠色狠狠色综合日日五| 欧美一区二区三区四区在线观看| 欧美永久精品| 在线视频成人| 欧美日韩国产成人在线免费| 在线亚洲精品| 久久男人资源视频| 亚洲精品人人| 国产精品免费看片| 乱码第一页成人| 99精品欧美一区二区蜜桃免费| 亚洲永久在线| 永久免费毛片在线播放不卡| 欧美黑人在线播放| 亚洲永久字幕| 欧美大片一区二区| 亚洲欧美日韩区| 136国产福利精品导航| 欧美午夜久久| 老司机午夜精品视频| 在线中文字幕一区| 欧美激情 亚洲a∨综合| 亚洲综合导航| 亚洲国产成人久久| 国产欧美日韩综合| 欧美日韩精品一区二区天天拍小说| 午夜亚洲视频| 亚洲麻豆av| 欧美成人免费全部观看天天性色| 亚洲影视九九影院在线观看| 亚洲国产精品福利| 国产精品午夜春色av| 欧美99久久| 久久免费高清视频| 亚洲欧美日韩国产综合精品二区| 亚洲国产cao| 免费观看成人网| 久久精品国产第一区二区三区最新章节| 亚洲看片一区| 亚洲人成在线观看| 噜噜噜噜噜久久久久久91| 亚洲欧美自拍偷拍| 亚洲影院污污.| 亚洲视频专区在线|