An easy to use event---By duyanning

该博客介绍了用标准C++编写的程序,其简单易理解和使用,参数数量无限制,可连接成员函数等。给出简单示例,说明了定义事件、连接目标对象及触发事件的方法。还阐述了事件与目标对象的连接管理,包括连接断开方式及注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Introduction

It is written in standard C++.
It is very simple, easy to understand and use.
You hardly have a chance to make a mistake.
There is no limit on the number of parameters.

You can connect to member function, function object or global function.

I have revised it to compile with GCC.
There is a Dev-C++ project file in the demo folder.

BUG fixed! 2005-11-07

A very simple example

// example1
#include <iostream>
#include <string>
#include "Event.hpp"

using namespace std;

class Edit {
    string s_;
public:
    // define event type 'TextChanged'
    EVENT_TYPE(TextChanged, (string s), (s));

    TextChanged changed;

    void set(string s)
    {
        s_ = s;

        // fire 'changed' event when the content of Edit is altered
        changed.fire(s_);
    }
};

class Dialog {
    Edit edit_;
public:
    void OnEditChanged(string s)
    {
        cout << "text in edit is : " << s << endl;
    }

    Dialog()
    {
        //edit_.changed.addListener(this, OnEditChanged);  // vc7.1
        edit_.changed.addListener(this, &Dialog::OnEditChanged);
    }

    void input(string s)
    {
        edit_.set(s);
    }

};

void example1()
{
    Dialog dlg;
    dlg.input("some text");
    dlg.input("another text");
}

As the example above suggests, it is very simple. What you need do is just defining an event, and then invokes its addListener method to connect it with the target object.

fire method is used to fire event.

The only thing confusing is

EVENT_TYPE(TextChanged, (string s), (s));

What dose these mean?
In fact, it's simple, the result after expanding of the macro is a class named TextChanged, just like

class TextChanged {
public:
    void fire(string s);
};

The parenthesis of (string s) and (s) should not be omitted.

 (string s) is called parameters list, which specifies the types and names of parameters that fire() method accept.

 (s) is called arguments list which specifies how to invoke fire() method, like fire(s).

 

Connection management

EVENT_TYPE(SomeEvent, (int x, int y), (x, y));
SomeEvent event1;

// function object
class Foo {
public:
    void operator()(int a, int b)
    {
        cout << "function object: " << a << '+' << b << '=' << a + b << endl;
    }
};

// ordinary function
void bar(int a, int b)
{
    cout << "function: " << a << '+' << b << '=' << a + b << endl;
}

void example2()
{
    Foo foo1;
    // connect to a function object
    SomeEvent::Connection c1(event1.addListener(foo1));

    SomeEvent::Connection c2;
    // connect to an ordinary function
    c2 = event1.addListener(bar);

    //SomeEvent::Connection c3(c1);    // error: copy construction is not permitted

    //c1 = c2;    // error: assignment is not permitted

    event1.fire(1, 2);

    {
        Foo foo2;
        SomeEvent::Connection c4(event1.addListener(foo2));

        // create an anonymous connection
        event1.addListener(bar);

        event1.fire(3, 4);

        // c4 break up automaticly
    }

    c1.disconnect();
    event1.fire(5, 6);

}

// connection's lifetime longer than event, no problem!
void example3()
{
	SomeEvent::Connection c;

	{
		SomeEvent event2;
		c = event2.addListener(bar);
		event2.fire(9, 9);
	}
	// you can invoke c.disconnect() explicitly or
	// rely on c's destructor to do it
}

addListener builds a connection between event and target object, linking each side.

If you assign the return value of addListener to a connection object, when the life time of this connection object is over, the connection between event and target object will break up, hence, there is no relation between each side.

Invoking disconnect method on connection object has the same effect.

If you did not assign the return value of addListener to certain connection object, there is an anonymous connection between event and target object, until the life time of event object is over, this connection will break up.

The connection between event and target object will not break up automatically. While the connection has not broken up and the target object is no longer exists, firing event will cause problem, so be cautious.

in order to ensure that there is no connection between target object and event after the target object's life time, you can either call the disconnect method of connection object before the target object's death, or make the connection as part of the target object. In most case, the latter is more preferable.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值