C++事件的实现

    技术2022-05-11  136

    C++ 事件的实现 2005-12-30 baickl Beijin

    简介

    本文将向你演示如何在标准 C++ 中实现 C++Builder 中的 __closure ,以及 C# 中的 __delegate 机制,所以在看本文之前,请确定自己对这些机制已经有所了解。通过本文你将可以领略 C++ 语言的无限魅力以及他的深奥。 ( 注:非经授权,请勿请将此文用于商业活动)

    原理探讨

    在探讨之前,先看一下 C# 里的 __delegate 的用法,请看下例: Delegate int SomeDelegate(string s, bool b); // 委托申明 rivate int SomeFunction(string str, bool bln){...} //某个类中的成员函数 SomeDelegate sd = new SomeDelegate(SomeFunction); //创建一个委托 sd(str,false); //由委托调用函数 上面部分为伪代码,相信接触过事件机构的人,都应该明白他的意思。由上面这段代码我们总结一下 C# 里委托的一些基本原理: 1.C# 中的委托是一个类,当你声明他的时候,就产生一个新的类型 2.C# 中的委托类创建的实例,可以通过函数的地址来初始化 3.C# 中的委托调用,实际上只是简单的调用被委托的函数 OK, 我们只需要了解这么多信息,如果有不对的地方,还请各位纠正。下面我们分析一下 C++ 中的事件的实现的困难度及原理。在 C++ 中我们实现的事件必须具备以下特性: 1. 事件所委托的函数的多样参数支持 2. 支持类成员函数类外部函数的委托 3.可以实现调用事件来达到调用委托函数的目的 上面的叙述,可能不是非常清楚,好吧,我就以具体的代码来说明这一切。我相信大部分技术人员还是不反感看代码的。在此做个声明,在C++中实现事件机构,绝对要用模板类来实现,除非你做的像Java里的事件机制,那我无话可说。 我们首先讨论第一个问题,这个问题是最难以被解决的。至少本人目前在网上所见到的事件机构,都只能支持一种参数。要么只有2个参数,要么只有3个参数,那我对这一块也做一些相关的讨论,以说明我的实现的原理。 其实在C++中,大家应该听过模板默认类型吧(听到这,某些人应该知道我所说的原理了),对,我就是用他来做对多参数的支持。看下面的声明: struct null_event{};//声明一个空类型,以作默认参数使用 template < typename RT, //返回值,以下是参数列表,注意,全部采用了默认参数 typename T0 = null_event, typename T1 = null_event, typename T2 = null_event, typename T3 = null_event, typename T4 = null_event, typename T5 = null_event, typename T6 = null_event, typename T7 = null_event, typename T8 = null_event, typename T9 = null_event, typename T10 = null_event, typename T11 = null_event > class BaseEvent { public: virtual~BaseEvent(){} //以下为调用形式,我给出了13种调用形式,分别对应13种情况 virtual RT Invoke()=0; virtual RT Invoke(T0)=0; virtual RT Invoke(T0,T1)=0; virtual RT Invoke(T0,T1,T2)=0; virtual RT Invoke(T0,T1,T2,T3)=0; virtual RT Invoke(T0,T1,T2,T3,T4)=0; virtual RT Invoke(T0,T1,T2,T3,T4,T5)=0; virtual RT Invoke(T0,T1,T2,T3,T4,T5,T6)=0; virtual RT Invoke(T0,T1,T2,T3,T4,T5,T6,T7)=0; virtual RT Invoke(T0,T1,T2,T3,T4,T5,T6,T7,T8)=0; virtual RT Invoke(T0,T1,T2,T3,T4,T5,T6,T7,T9,T9)=0; virtual RT Invoke(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10)=0; virtual RT Invoke(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11)=0; }; 我们的事件基类虽然被创建出来了,但我们需要做的还很多,我们需要解决怎么将类成员函数和类外部函数同事件类相挂接。这一部分需要通过派生类来实现。首先我们看看类外部函数事件的实现: template < typename RT,//下面的形式是不是很熟悉? typename T0 = null_event, typename T1 = null_event, typename T2 = null_event, typename T3 = null_event, typename T4 = null_event, typename T5 = null_event, typename T6 = null_event, typename T7 = null_event, typename T8 = null_event, typename T9 = null_event,typename T10 = null_event,typename T11 = null_event > class NormalEvent:public BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11> { private: //定义不同类型的函数,参数支持范围为0-12 typedef RT (*FUN0) (); typedef RT (*FUN1) (T0); typedef RT (*FUN2) (T0,T1); typedef RT (*FUN3) (T0,T1,T2); typedef RT (*FUN4) (T0,T1,T2,T3); typedef RT (*FUN5) (T0,T1,T2,T3,T4); typedef RT (*FUN6) (T0,T1,T2,T3,T4,T5); typedef RT (*FUN7) (T0,T1,T2,T3,T4,T5,T6); typedef RT (*FUN8) (T0,T1,T2,T3,T4,T5,T6,T7); typedef RT (*FUN9) (T0,T1,T2,T3,T4,T5,T6,T7,T8); typedef RT (*FUN10)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9); typedef RT (*FUN11)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10); typedef RT (*FUN12)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11); private: //创建函数的指针 FUN0 m_Fun0; FUN1 m_Fun1; FUN2 m_Fun2; FUN3 m_Fun3; FUN4 m_Fun4; FUN5 m_Fun5; FUN6 m_Fun6; FUN7 m_Fun7; FUN8 m_Fun8; FUN9 m_Fun9; FUN10 m_Fun10; FUN11 m_Fun11; FUN12 m_Fun12; //默认初始化工作 void Default() { m_Fun0=0; m_Fun1=0; m_Fun2=0; m_Fun3=0; m_Fun4=0; m_Fun5=0; m_Fun6=0; m_Fun7=0; m_Fun8=0; m_Fun9=0; m_Fun10=0; m_Fun11=0; m_Fun12=0; } public: //其实关键都在这些构造函数里,因为构造函数有13种, //所以支持13种类型的外部函数被挂接到事件对象中 NormalEvent(FUN0 Fun) { assert(Fun!=0); Default(); m_Fun0=Fun; } NormalEvent(FUN1 Fun) { assert(Fun!=0); Default(); m_Fun1=Fun; } NormalEvent(FUN2 Fun) { assert(Fun!=0); Default(); m_Fun2=Fun; } NormalEvent(FUN3 Fun) { assert(Fun!=0); Default(); m_Fun3=Fun; } //被省略的部分。。。 NormalEvent(FUN12 Fun) { assert(Fun!=0); Default(); m_Fun12=Fun; } //以下是不同形式的调用,取决于你的函数参数,不多做说明 virtual RT Invoke()//挂接无参函数的委托调用 { assert(m_Fun0!=0); return (*m_Fun0)(); } virtual RT Invoke(T0 _0)//挂接一个参数函数的委托调用 { assert(m_Fun1!=0); return(*m_Fun1)(_0); } virtual RT Invoke(T0 _0 , T1 _1)//挂接两个参数函数的委托调用 { assert(m_Fun2!=0); return(*m_Fun2)(_0,_1); } . . 省略一部分。。其实大家都知道 . virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9 , T10 _10 , T11 _11) { assert(m_Fun12!=0); return(*m_Fun12)(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11); } }; 到上面这一部分,应该比较明了了。因为原理已经很清楚,是不是有点像boost里的tuple实现机制,没错,就是他。对于类外部函数的调用就已经非常明了,我们还需要给几一些函数来做最基本的挂接工作,如下,先不说明为什么这么说,看到后面大家就会明白了。 template<typename RT> BaseEvent<RT>*EventHandler(RT (*fun)()) { return new NormalEvent<RT>(fun); } template<typename RT,typename T0> BaseEvent<RT,T0>*EventHandler(RT (*fun)(T0)) { return new NormalEvent<RT,T0>(fun); } template<typename RT,typename T0,typename T1> BaseEvent<RT,T0,T1>*EventHandler(RT (*fun)(T0,T1)) { return new NormalEvent<RT,T0,T1>(fun); } //以下省略.. 上面是对类外部事件的完成,那么对类成员函数事件的原理也是一样的,我们仅贴出相关的代码不多做说明,在最后的时候,会介绍一个整合的类,用以完成对事件的更完整的描述及封装。 template < typename C, typename RT, typename T0 = null_event,typename T1 = null_event,typename T2 = null_event,typename T3 = null_event, typename T4 = null_event,typename T5 = null_event,typename T6 = null_event,typename T7 = null_event, typename T8 = null_event,typename T9 = null_event,typename T10 = null_event,typename T11 = null_event > class MemberEvent:public BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11> { private: typedef RT (C::*FUN0) (); typedef RT (C::*FUN1) (T0); typedef RT (C::*FUN2) (T0,T1); typedef RT (C::*FUN3) (T0,T1,T2); typedef RT (C::*FUN4) (T0,T1,T2,T3); typedef RT (C::*FUN5) (T0,T1,T2,T3,T4); typedef RT (C::*FUN6) (T0,T1,T2,T3,T4,T5); typedef RT (C::*FUN7) (T0,T1,T2,T3,T4,T5,T6); typedef RT (C::*FUN8) (T0,T1,T2,T3,T4,T5,T6,T7); typedef RT (C::*FUN9) (T0,T1,T2,T3,T4,T5,T6,T7,T8); typedef RT (C::*FUN10)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9); typedef RT (C::*FUN11)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10); typedef RT (C::*FUN12)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11); private: FUN0 m_Fun0; FUN1 m_Fun1; FUN2 m_Fun2; FUN3 m_Fun3; FUN4 m_Fun4; FUN5 m_Fun5; FUN6 m_Fun6; FUN7 m_Fun7; FUN8 m_Fun8; FUN9 m_Fun9; FUN10 m_Fun10; FUN11 m_Fun11; FUN12 m_Fun12; C *m_Object; void Default() { m_Fun0=0; m_Fun1=0; m_Fun2=0; m_Fun3=0; m_Fun4=0; m_Fun5=0; m_Fun6=0; m_Fun7=0; m_Fun8=0; m_Fun9=0; m_Fun10=0; m_Fun11=0; m_Fun12=0; m_Object=0; } public: MemberEvent(C*pObject,FUN0 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun0=Fun; m_Object=pObject; } MemberEvent(C*pObject,FUN1 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun1=Fun; m_Object=pObject; } MemberEvent(C*pObject,FUN2 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun2=Fun; m_Object=pObject; } //中间省略。。。 MemberEvent(C*pObject,FUN12 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun12=Fun; m_Object=pObject; } virtual RT Invoke() { assert(m_Object!=0); assert(m_Fun0!=0); return (m_Object->*m_Fun0)(); } virtual RT Invoke(T0 _0) { assert(m_Object!=0); assert(m_Fun1!=0); return(m_Object->*m_Fun1)(_0); } virtual RT Invoke(T0 _0 , T1 _1) { assert(m_Object!=0); assert(m_Fun2!=0); return(m_Object->*m_Fun2)(_0,_1); } //中间省略 virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9 , T10 _10 , T11 _11) { assert(m_Object!=0); assert(m_Fun12!=0); return(m_Object->*m_Fun12)(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11); } }; template < typename C,typename RT > BaseEvent<RT>*EventHandler(C*obj,RT (C::*fun)()) { return new MemberEvent<C,RT>(obj,fun); } template < typename C,typename RT,typename T0 > BaseEvent<RT,T0>*EventHandler(C*obj,RT (C::*fun)(T0)) { return new MemberEvent<C,RT,T0>(obj,fun); } template < typename C,typename RT,typename T0,typename T1 > BaseEvent<RT,T0,T1>*EventHandler(C*obj,RT (C::*fun)(T0,T1)) { return new MemberEvent<C,RT,T0,T1>(obj,fun); } template < typename C,typename RT,typename T0,typename T1,typename T2 > BaseEvent<RT,T0,T1,T2>*EventHandler(C*obj,RT (C::*fun)(T0,T1,T2)) { return new MemberEvent<C,RT,T0,T1,T2>(obj,fun); } //以下部分省略 以下为最终封装类的代码不做多说,大家一会看到示例就会明白了。: template < typename RT, typename T0 = null_event,typename T1 = null_event,typename T2 = null_event,typename T3 = null_event, typename T4 = null_event,typename T5 = null_event,typename T6 = null_event,typename T7 = null_event, typename T8 = null_event,typename T9 = null_event,typename T10 = null_event,typename T11 = null_event > class __Event { typedef BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>*eventHandler; private: eventHandler m_EventHandler; public: bool IsValid()const { if(m_EventHandler!=0) return true; else return false; } public: __Event() { m_EventHandler=0; } virtual~__Event() { if(m_EventHandler!=0) { delete m_EventHandler; m_EventHandler=0; } } void operator=(BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>*event) { if(m_EventHandler!=0) { delete m_EventHandler; m_EventHandler=0; } m_EventHandler=event; } RT Invoke() { assert(m_EventHandler!=0); return m_EventHandler->Invoke(); } RT Invoke(T0 _0) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0); } RT Invoke(T0 _0 , T1 _1) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1); } RT Invoke(T0 _0 , T1 _1 , T2 _2) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2); } //省略相关代码 RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9 , T10 _10 , T11 _11) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3 ,_4,_5,_6,_7,_8,_9,_10,_11); } RT operator()() { assert(m_EventHandler!=0); return m_EventHandler->Invoke(); } RT operator()(T0 _0) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0); } RT operator()(T0 _0 , T1 _1) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1); } RT operator()(T0 _0 , T1 _1 , T2 _2) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2); } //省略相关代码 RT operator()(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9 , T10 _10 , T11 _11) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3 ,_4,_5,_6,_7,_8,_9,_10,_11); } }; 以上就是具体的实现过程,具体的全部源代码在下面一栏,具体实现里给出

    具体实现

    #ifndef EVENT_INCLUDE #define EVENT_INCLUDE #include<assert.h> #pragma warning(disable:4251) namespace KtyGE { struct null_event{}; template < typename RT, typename T0 = null_event,typename T1 = null_event,typename T2 = null_event,typename T3 = null_event, typename T4 = null_event,typename T5 = null_event,typename T6 = null_event,typename T7 = null_event, typename T8 = null_event,typename T9 = null_event,typename T10 = null_event,typename T11 = null_event > class BaseEvent { public: virtual~BaseEvent(){} virtual RT Invoke()=0; virtual RT Invoke(T0)=0; virtual RT Invoke(T0,T1)=0; virtual RT Invoke(T0,T1,T2)=0; virtual RT Invoke(T0,T1,T2,T3)=0; virtual RT Invoke(T0,T1,T2,T3,T4)=0; virtual RT Invoke(T0,T1,T2,T3,T4,T5)=0; virtual RT Invoke(T0,T1,T2,T3,T4,T5,T6)=0; virtual RT Invoke(T0,T1,T2,T3,T4,T5,T6,T7)=0; virtual RT Invoke(T0,T1,T2,T3,T4,T5,T6,T7,T8)=0; virtual RT Invoke(T0,T1,T2,T3,T4,T5,T6,T7,T9,T9)=0; virtual RT Invoke(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10)=0; virtual RT Invoke(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11)=0; }; template < typename RT, typename T0 = null_event,typename T1 = null_event,typename T2 = null_event,typename T3 = null_event, typename T4 = null_event,typename T5 = null_event,typename T6 = null_event,typename T7 = null_event, typename T8 = null_event,typename T9 = null_event,typename T10 = null_event,typename T11 = null_event > class NormalEvent:public BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11> { private: typedef RT (*FUN0) (); typedef RT (*FUN1) (T0); typedef RT (*FUN2) (T0,T1); typedef RT (*FUN3) (T0,T1,T2); typedef RT (*FUN4) (T0,T1,T2,T3); typedef RT (*FUN5) (T0,T1,T2,T3,T4); typedef RT (*FUN6) (T0,T1,T2,T3,T4,T5); typedef RT (*FUN7) (T0,T1,T2,T3,T4,T5,T6); typedef RT (*FUN8) (T0,T1,T2,T3,T4,T5,T6,T7); typedef RT (*FUN9) (T0,T1,T2,T3,T4,T5,T6,T7,T8); typedef RT (*FUN10)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9); typedef RT (*FUN11)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10); typedef RT (*FUN12)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11); private: FUN0 m_Fun0; FUN1 m_Fun1; FUN2 m_Fun2; FUN3 m_Fun3; FUN4 m_Fun4; FUN5 m_Fun5; FUN6 m_Fun6; FUN7 m_Fun7; FUN8 m_Fun8; FUN9 m_Fun9; FUN10 m_Fun10; FUN11 m_Fun11; FUN12 m_Fun12; void Default() { m_Fun0=0; m_Fun1=0; m_Fun2=0; m_Fun3=0; m_Fun4=0; m_Fun5=0; m_Fun6=0; m_Fun7=0; m_Fun8=0; m_Fun9=0; m_Fun10=0; m_Fun11=0; m_Fun12=0; } public: NormalEvent(FUN0 Fun) { assert(Fun!=0); Default(); m_Fun0=Fun; } NormalEvent(FUN1 Fun) { assert(Fun!=0); Default(); m_Fun1=Fun; } NormalEvent(FUN2 Fun) { assert(Fun!=0); Default(); m_Fun2=Fun; } NormalEvent(FUN3 Fun) { assert(Fun!=0); Default(); m_Fun3=Fun; } NormalEvent(FUN4 Fun) { assert(Fun!=0); Default(); m_Fun4=Fun; } NormalEvent(FUN5 Fun) { assert(Fun!=0); Default(); m_Fun5=Fun; } NormalEvent(FUN6 Fun) { assert(Fun!=0); Default(); m_Fun6=Fun; } NormalEvent(FUN7 Fun) { assert(Fun!=0); Default(); m_Fun7=Fun; } NormalEvent(FUN8 Fun) { assert(Fun!=0); Default(); m_Fun8=Fun; } NormalEvent(FUN9 Fun) { assert(Fun!=0); Default(); m_Fun9=Fun; } NormalEvent(FUN10 Fun) { assert(Fun!=0); Default(); m_Fun10=Fun; } NormalEvent(FUN11 Fun) { assert(Fun!=0); Default(); m_Fun11=Fun; } NormalEvent(FUN12 Fun) { assert(Fun!=0); Default(); m_Fun12=Fun; } virtual RT Invoke() { assert(m_Fun0!=0); return (*m_Fun0)(); } virtual RT Invoke(T0 _0) { assert(m_Fun1!=0); return(*m_Fun1)(_0); } virtual RT Invoke(T0 _0 , T1 _1) { assert(m_Fun2!=0); return(*m_Fun2)(_0,_1); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2) { assert(m_Fun3!=0); return(*m_Fun3)(_0,_1,_2); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3) { assert(m_Fun4!=0); return(*m_Fun4)(_0,_1,_2,_3); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4) { assert(m_Fun5!=0); return(*m_Fun5)(_0,_1,_2,_3,_4); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5) { assert(m_Fun6!=0); return(*m_Fun6)(_0,_1,_2,_3,_4,_5); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6) { assert(m_Fun7!=0); return(*m_Fun7)(_0,_1,_2,_3,_4,_5,_6); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7) { assert(m_Fun8!=0); return(*m_Fun8)(_0,_1,_2,_3,_4,_5,_6,_7); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8) { assert(m_Fun9!=0); return(*m_Fun9)(_0,_1,_2,_3,_4,_5,_6,_7,_8); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9) { assert(m_Fun10!=0); return(*m_Fun10)(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9 , T10 _10) { assert(m_Fun11!=0); return(*m_Fun11)(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9 , T10 _10 , T11 _11) { assert(m_Fun12!=0); return(*m_Fun12)(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11); } }; template < typename RT > BaseEvent<RT>*EventHandler(RT (*fun)()) { return new NormalEvent<RT>(fun); } template < typename RT,typename T0 > BaseEvent<RT,T0>*EventHandler(RT (*fun)(T0)) { return new NormalEvent<RT,T0>(fun); } template < typename RT,typename T0,typename T1 > BaseEvent<RT,T0,T1>*EventHandler(RT (*fun)(T0,T1)) { return new NormalEvent<RT,T0,T1>(fun); } template < typename RT,typename T0,typename T1,typename T2 > BaseEvent<RT,T0,T1,T2>*EventHandler(RT (*fun)(T0,T1,T2)) { return new NormalEvent<RT,T0,T1,T2>(fun); } template < typename RT,typename T0,typename T1,typename T2,typename T3 > BaseEvent<RT,T0,T1,T2,T3>*EventHandler(RT (*fun)(T0,T1,T2,T3)) { return new NormalEvent<RT,T0,T1,T2,T3>(fun); } template < typename RT, typename T0,typename T1,typename T2,typename T3,typename T4 > BaseEvent<RT,T0,T1,T2,T3,T4>*EventHandler(RT (*fun)(T0,T1,T2,T3,T4)) { return new NormalEvent<RT,T0,T1,T2,T3,T4>(fun); } template < typename RT, typename T0,typename T1,typename T2,typename T3,typename T4, typename T5 > BaseEvent<RT,T0,T1,T2,T3,T4,T5>*EventHandler(RT (*fun)(T0,T1,T2,T3,T4,T5)) { return new NormalEvent<RT,T0,T1,T2,T3,T4,T5>(fun); } template < typename RT, typename T0,typename T1,typename T2,typename T3,typename T4, typename T5,typename T6 > BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6>*EventHandler(RT (*fun)(T0,T1,T2,T3,T4,T5,T6)) { return new NormalEvent<RT,T0,T1,T2,T3,T4,T5,T6>(fun); } template < typename RT, typename T0,typename T1,typename T2,typename T3,typename T4, typename T5,typename T6,typename T7 > BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7>*EventHandler(RT (*fun)(T0,T1,T2,T3,T4,T5,T6,T7)) { return new NormalEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7>(fun); } template < typename RT, typename T0,typename T1,typename T2,typename T3,typename T4, typename T5,typename T6,typename T7,typename T8 > BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8>*EventHandler(RT (*fun)(T0,T1,T2,T3,T4,T5,T6,T7,T8)) { return new NormalEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8>(fun); } template < typename RT, typename T0,typename T1,typename T2,typename T3,typename T4, typename T5,typename T6,typename T7,typename T8,typename T9 > BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>*EventHandler(RT (*fun)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9)) { return new NormalEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>(fun); } template < typename RT, typename T0,typename T1,typename T2,typename T3,typename T4, typename T5,typename T6,typename T7,typename T8,typename T9, typename T10 > BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>*EventHandler(RT (*fun)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10)) { return new NormalEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>(fun); } template < typename RT, typename T0,typename T1,typename T2,typename T3,typename T4, typename T5,typename T6,typename T7,typename T8,typename T9, typename T10,typename T11 > BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>*EventHandler(RT (*fun)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11)) { return new NormalEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>(fun); } template < typename C, typename RT, typename T0 = null_event,typename T1 = null_event,typename T2 = null_event,typename T3 = null_event, typename T4 = null_event,typename T5 = null_event,typename T6 = null_event,typename T7 = null_event, typename T8 = null_event,typename T9 = null_event,typename T10 = null_event,typename T11 = null_event > class MemberEvent:public BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11> { private: typedef RT (C::*FUN0) (); typedef RT (C::*FUN1) (T0); typedef RT (C::*FUN2) (T0,T1); typedef RT (C::*FUN3) (T0,T1,T2); typedef RT (C::*FUN4) (T0,T1,T2,T3); typedef RT (C::*FUN5) (T0,T1,T2,T3,T4); typedef RT (C::*FUN6) (T0,T1,T2,T3,T4,T5); typedef RT (C::*FUN7) (T0,T1,T2,T3,T4,T5,T6); typedef RT (C::*FUN8) (T0,T1,T2,T3,T4,T5,T6,T7); typedef RT (C::*FUN9) (T0,T1,T2,T3,T4,T5,T6,T7,T8); typedef RT (C::*FUN10)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9); typedef RT (C::*FUN11)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10); typedef RT (C::*FUN12)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11); private: FUN0 m_Fun0; FUN1 m_Fun1; FUN2 m_Fun2; FUN3 m_Fun3; FUN4 m_Fun4; FUN5 m_Fun5; FUN6 m_Fun6; FUN7 m_Fun7; FUN8 m_Fun8; FUN9 m_Fun9; FUN10 m_Fun10; FUN11 m_Fun11; FUN12 m_Fun12; C *m_Object; void Default() { m_Fun0=0; m_Fun1=0; m_Fun2=0; m_Fun3=0; m_Fun4=0; m_Fun5=0; m_Fun6=0; m_Fun7=0; m_Fun8=0; m_Fun9=0; m_Fun10=0; m_Fun11=0; m_Fun12=0; m_Object=0; } public: MemberEvent(C*pObject,FUN0 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun0=Fun; m_Object=pObject; } MemberEvent(C*pObject,FUN1 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun1=Fun; m_Object=pObject; } MemberEvent(C*pObject,FUN2 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun2=Fun; m_Object=pObject; } MemberEvent(C*pObject,FUN3 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun3=Fun; m_Object=pObject; } MemberEvent(C*pObject,FUN4 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun4=Fun; m_Object=pObject; } MemberEvent(C*pObject,FUN5 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun5=Fun; m_Object=pObject; } MemberEvent(C*pObject,FUN6 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun6=Fun; m_Object=pObject; } MemberEvent(C*pObject,FUN7 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun7=Fun; m_Object=pObject; } MemberEvent(C*pObject,FUN8 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun8=Fun; m_Object=pObject; } MemberEvent(C*pObject,FUN9 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun9=Fun; m_Object=pObject; } MemberEvent(C*pObject,FUN10 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun10=Fun; m_Object=pObject; } MemberEvent(C*pObject,FUN11 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun11=Fun; m_Object=pObject; } MemberEvent(C*pObject,FUN12 Fun) { assert(pObject!=0 && Fun!=0); Default(); m_Fun12=Fun; m_Object=pObject; } virtual RT Invoke() { assert(m_Object!=0); assert(m_Fun0!=0); return (m_Object->*m_Fun0)(); } virtual RT Invoke(T0 _0) { assert(m_Object!=0); assert(m_Fun1!=0); return(m_Object->*m_Fun1)(_0); } virtual RT Invoke(T0 _0 , T1 _1) { assert(m_Object!=0); assert(m_Fun2!=0); return(m_Object->*m_Fun2)(_0,_1); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2) { assert(m_Object!=0); assert(m_Fun3!=0); return(m_Object->*m_Fun3)(_0,_1,_2); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3) { assert(m_Object!=0); assert(m_Fun4!=0); return(m_Object->*m_Fun4)(_0,_1,_2,_3); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4) { assert(m_Object!=0); assert(m_Fun5!=0); return(m_Object->*m_Fun5)(_0,_1,_2,_3,_4); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5) { assert(m_Object!=0); assert(m_Fun6!=0); return(m_Object->*m_Fun6)(_0,_1,_2,_3,_4,_5); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6) { assert(m_Object!=0); assert(m_Fun7!=0); return(m_Object->*m_Fun7)(_0,_1,_2,_3,_4,_5,_6); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7) { assert(m_Object!=0); assert(m_Fun8!=0); return(m_Object->*m_Fun8)(_0,_1,_2,_3,_4,_5,_6,_7); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8) { assert(m_Object!=0); assert(m_Fun9!=0); return(m_Object->*m_Fun9)(_0,_1,_2,_3,_4,_5,_6,_7,_8); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9) { assert(m_Object!=0); assert(m_Fun10!=0); return(m_Object->*m_Fun10)(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9 , T10 _10) { assert(m_Object!=0); assert(m_Fun11!=0); return(m_Object->*m_Fun11)(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10); } virtual RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9 , T10 _10 , T11 _11) { assert(m_Object!=0); assert(m_Fun12!=0); return(m_Object->*m_Fun12)(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11); } }; template < typename C,typename RT > BaseEvent<RT>*EventHandler(C*obj,RT (C::*fun)()) { return new MemberEvent<C,RT>(obj,fun); } template < typename C,typename RT,typename T0 > BaseEvent<RT,T0>*EventHandler(C*obj,RT (C::*fun)(T0)) { return new MemberEvent<C,RT,T0>(obj,fun); } template < typename C,typename RT,typename T0,typename T1 > BaseEvent<RT,T0,T1>*EventHandler(C*obj,RT (C::*fun)(T0,T1)) { return new MemberEvent<C,RT,T0,T1>(obj,fun); } template < typename C,typename RT,typename T0,typename T1,typename T2 > BaseEvent<RT,T0,T1,T2>*EventHandler(C*obj,RT (C::*fun)(T0,T1,T2)) { return new MemberEvent<C,RT,T0,T1,T2>(obj,fun); } template < typename C,typename RT,typename T0,typename T1,typename T2,typename T3 > BaseEvent<RT,T0,T1,T2,T3>*EventHandler(C*obj,RT (C::*fun)(T0,T1,T2,T3)) { return new MemberEvent<C,RT,T0,T1,T2,T3>(obj,fun); } template < typename C,typename RT,typename T0,typename T1,typename T2,typename T3, typename T4 > BaseEvent<RT,T0,T1,T2,T3,T4>*EventHandler(C*obj,RT (C::*fun)(T0,T1,T2,T3,T4)) { return new MemberEvent<C,RT,T0,T1,T2,T3,T4>(obj,fun); } template < typename C,typename RT,typename T0,typename T1,typename T2,typename T3, typename T4,typename T5 > BaseEvent<RT,T0,T1,T2,T3,T4,T5>*EventHandler(C*obj,RT (C::*fun)(T0,T1,T2,T3,T4,T5)) { return new MemberEvent<C,RT,T0,T1,T2,T3,T4,T5>(obj,fun); } template < typename C,typename RT,typename T0,typename T1,typename T2,typename T3, typename T4,typename T5,typename T6 > BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6>*EventHandler(C*obj,RT (C::*fun)(T0,T1,T2,T3,T4,T5,T6)) { return new MemberEvent<C,RT,T0,T1,T2,T3,T4,T5,T6>(obj,fun); } template < typename C,typename RT,typename T0,typename T1,typename T2,typename T3, typename T4,typename T5,typename T6,typename T7 > BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7>*EventHandler(C*obj,RT (C::*fun)(T0,T1,T2,T3,T4,T5,T6,T7)) { return new MemberEvent<C,RT,T0,T1,T2,T3,T4,T5,T6,T7>(obj,fun); } template < typename C,typename RT,typename T0,typename T1,typename T2,typename T3, typename T4,typename T5,typename T6,typename T7,typename T8 > BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8>*EventHandler(C*obj,RT (C::*fun)(T0,T1,T2,T3,T4,T5,T6,T7,T8)) { return new MemberEvent<C,RT,T0,T1,T2,T3,T4,T5,T6,T7,T8>(obj,fun); } template < typename C,typename RT,typename T0,typename T1,typename T2,typename T3, typename T4,typename T5,typename T6,typename T7,typename T8,typename T9 > BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>*EventHandler(C*obj,RT (C::*fun)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9)) { return new MemberEvent<C,RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>(obj,fun); } template < typename C,typename RT,typename T0,typename T1,typename T2,typename T3, typename T4,typename T5,typename T6,typename T7,typename T8,typename T9, typename T10 > BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>*EventHandler(C*obj,RT (C::*fun)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10)) { return new MemberEvent<C,RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>(obj,fun); } template < typename C,typename RT,typename T0,typename T1,typename T2,typename T3, typename T4,typename T5,typename T6,typename T7,typename T8,typename T9, typename T10,typename T11 > BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>*EventHandler(C*obj,RT (C::*fun)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11)) { return new MemberEvent<C,RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>(obj,fun); } template < typename RT, typename T0 = null_event,typename T1 = null_event,typename T2 = null_event,typename T3 = null_event, typename T4 = null_event,typename T5 = null_event,typename T6 = null_event,typename T7 = null_event, typename T8 = null_event,typename T9 = null_event,typename T10 = null_event,typename T11 = null_event > class __Event { typedef BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>*eventHandler; private: eventHandler m_EventHandler; public: bool IsValid()const { if(m_EventHandler!=0) return true; else return false; } public: __Event() { m_EventHandler=0; } virtual~__Event() { if(m_EventHandler!=0) { delete m_EventHandler; m_EventHandler=0; } } void operator=(BaseEvent<RT,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>*event) { if(m_EventHandler!=0) { delete m_EventHandler; m_EventHandler=0; } m_EventHandler=event; } RT Invoke() { assert(m_EventHandler!=0); return m_EventHandler->Invoke(); } RT Invoke(T0 _0) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0); } RT Invoke(T0 _0 , T1 _1) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1); } RT Invoke(T0 _0 , T1 _1 , T2 _2) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2); } RT Invoke(T0 _0,T1 _1,T2 _2,T3 _3) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3); } RT Invoke(T0 _0,T1 _1,T2 _2,T3 _3 , T4 _4) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3,_4); } RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3,_4,_5); } RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3,_4,_5,_6); } RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3,_4,_5,_6,_7); } RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3,_4,_5,_6,_7,_8); } RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9); } RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9 , T10 _10) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10); } RT Invoke(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9 , T10 _10 , T11 _11) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3 ,_4,_5,_6,_7,_8,_9,_10,_11); } RT operator()() { assert(m_EventHandler!=0); return m_EventHandler->Invoke(); } RT operator()(T0 _0) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0); } RT operator()(T0 _0 , T1 _1) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1); } RT operator()(T0 _0 , T1 _1 , T2 _2) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2); } RT operator()(T0 _0,T1 _1,T2 _2,T3 _3) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3); } RT operator()(T0 _0,T1 _1,T2 _2,T3 _3 , T4 _4) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3,_4); } RT operator()(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3,_4,_5); } RT operator()(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3,_4,_5,_6); } RT operator()(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3,_4,_5,_6,_7); } RT operator()(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3,_4,_5,_6,_7,_8); } RT operator()(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9); } RT operator()(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9 , T10 _10) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10); } RT operator()(T0 _0 , T1 _1 , T2 _2 , T3 _3 , T4 _4 , T5 _5 , T6 _6 , T7 _7 , T8 _8 , T9 _9 , T10 _10 , T11 _11) { assert(m_EventHandler!=0); return m_EventHandler->Invoke(_0,_1,_2,_3 ,_4,_5,_6,_7,_8,_9,_10,_11); } }; }//KtyGE #endif//__EVENT_INCLUDE 以下为一示例。大家可以参考着使用: #include "Event.H" #include <iostream> using namespace std; void ProcArg3(int a,int b,int c) { cout<<"Call In ProcArg3."<<endl; } void ProcArg2(int a,int b) { cout<<"Call In ProcArg2."<<endl; } class Test { private: void ProcArg1(int ) { cout<<"Call In Test::ProcArg1."<<endl; } void ProcArg0() { cout<<"Call In Test::ProcArg0."<<endl; } public: __Event<void,int,int,int> OnArg3Func; __Event<void,int,int> OnArg2Func; __Event<void,int> OnArg1Func; __Event<void> OnArg0Func; Test() { OnArg3Func=EventHandler(ProcArg3); //外部函数处理事件 OnArg2Func=EventHandler(ProcArg2); //不同参数的处理 OnArg1Func=EventHandler(this,ProcArg1); //类成员函数事件处理 OnArg0Func=EventHandler(this,ProcArg0); } void Invoke() { OnArg0Func.Invoke(); OnArg1Func.Invoke(0); OnArg2Func.Invoke(0,0); OnArg3Func.Invoke(0,0,0) ; //调用事件 } }; void main() { Test *t=new Test; t->Invoke(); cin.get(); }

    后记

    原本,我以为在 C++中用软件是无法成功实现 C#中的委托的,但是在我实现的那一刻起,我知道 C++语言的灵活,有些是你难以想到的。在 2006年到来之际,谨以此文,献给所有的 C++爱好者。如果有用词不当,或是不明了的地方,请与我联系。 QQ:49448699 EM:baickl@163.com http://blog.csdn.net/baickl

    最新回复(0)