让C++也来支持事件

让C++也来支持事件?

(http://blog.csdn.net/wqf2/)

        面向对象发展到今天,人们已经不满足于对一个事物的描述仅停留在属性和方法上了。事件也作为对象的基本组成部分,被新兴的面向对象语言所采纳。 所谓事件就是一个对象在某个特定的条件下触发通知对象的创建者,由创建者来进行相应的处理。我们可以看到事件的真实处理过程并不被包装在对象里。在java,c#,dephi等语言中都提供了对事件的支持,或者以关键字的形式,或者以类库的形式。而c++中见不到任何关于事件的关键字和类库,难道c++就无法拥有事件这个特性吗?只要动动脑筋就没有难事。现在我们就让c++也来支持事件。
        这里仅从语言上考虑,而不使用任何平台相关的特性(消息,事件对象...)。因此我拿出两种实现方法,一种是采用函数指针,另一种采用虚函数。
        1. 采用函数指针方式,代码如下:
 

#include <IOSTREAM>
using namespace std;

//定义事件函数的类型
typedef void (*EOnBeforeInvoke)();
typedef void (*EOnAfterInvoke)();

//一个拥有事件的类
class CSomeObject1
{
public:
	//定义事件
	EOnBeforeInvoke OnBeforeInvoke; //调用前事件
	EOnAfterInvoke  OnAfterInvoke;  //调用后事件	
public:
	CSomeObject1()
	{
		OnBeforeInvoke = NULL;
		OnAfterInvoke = NULL;
	}

	void Invoke()
	{
		//触发OnBeforeInvoke事件
		if (OnBeforeInvoke != NULL)
			OnBeforeInvoke();
		
		cout << "CSomeObject1::Invoke()" <<endl;

		//触发OnAfterInvoke事件
		if (OnAfterInvoke != NULL)
			OnAfterInvoke();
	}
};

//CSomeObject1对象的创建者类
class CEventTest1
{
	CSomeObject1 m_objSome;

	static void  OnBeforeInvoke()
	{
		cout<< "调用前..." <<endl;
	}
	static void  OnAfterInvoke()
	{
		cout<< "调用后..." <<endl;
	}
	//安装事件
	void InstallEvents()
	{
		m_objSome.OnBeforeInvoke = OnBeforeInvoke;
		m_objSome.OnAfterInvoke = OnAfterInvoke;
	}
	//卸载事件
	void UninstallEvents()
	{
		m_objSome.OnBeforeInvoke = NULL;
		m_objSome.OnAfterInvoke = NULL;
		
	}

public:
	CEventTest1()
	{
		InstallEvents();
	}
	
	~CEventTest1()
	{
		UninstallEvents();
	}

	void Invoke()
	{
		m_objSome.Invoke();
	}
};
 
int main(int argc, char* argv[])
{
	CEventTest1 test1;
	test1.Invoke();
}


        记得当年在TurboC下编程时,虽然没有c++,但依然可以写出面向对象的代码,就是利用struct里添加函数指针域的方式,来实现现在c++中的class。如今函数指针依然有用武之地。

        2. 采用虚拟函数的形式,代码如下:

#include <IOSTREAM>
using namespace std;

//事件接口
class  __declspec(novtable) ISomeObject2Events
{
	friend class CSomeObject2;
protected:
	virtual void OnBeforeInvoke();
	virtual void OnAfterInvoke();
};

//一个拥有事件的类
class CSomeObject2
{
public:
	ISomeObject2Events * m_pEvents;
	void Invoke()
	{
		//触发OnBeforeInvoke事件
		if (m_pEvents != NULL)
			m_pEvents->OnBeforeInvoke();
		
		cout<<"CSomeObject2::Invoke()"<<endl;
		
		//触发OnAfterInvoke事件
		if (m_pEvents != NULL)
			m_pEvents->OnAfterInvoke();
	}
};

//CSomeObject2对象的创建者类
class CEventTest2 : public ISomeObject2Events
{

	CSomeObject2 m_objSome;
	//调用前事件处理
	virtual void OnBeforeInvoke()
	{ 
		cout<< "调用前..." <<endl;
	};
	//调用后事件处理
	virtual void OnAfterInvoke()
	{ 
		cout << "调用后..." <<endl;
	};

	//安装事件
	void InstallEvents()
	{
		m_objSome.m_pEvents = this;
	}
	//卸载事件
	void UninstallEvents()
	{
		m_objSome.m_pEvents = NULL;
	}

public:
	CEventTest2()
	{
		InstallEvents();
	}
	
	~CEventTest2()
	{
		UninstallEvents();
	}

	void Invoke()
	{
		m_objSome.Invoke();
	}

};

int main(int argc, char* argv[])
{
	CEventTest2 test2;
	test2.Invoke();
}

        这两种方式各有利弊,使用函数指针的好处是触发事件效率高。而采用虚函数的形式的好处是代码更令活更清晰一些。大家可以凭喜好来选择。如果大家看过之后有什么指教或补充,请千万别吝惜你的思想和文字。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值