将任何类型的参数附加到事件

时间:2013-12-13 00:55:56

标签: c++ events generic-programming

我对泛型编程几乎没有经验(我很少需要它),但我现在正在尝试为我的应用程序实现一个事件系统。这就是我对实际事件的想法:

template <typename Arg_Type> struct Event {
    std::vector<std::string> ids; // All the objects to pass the event to
    Action action;                // Action to perform (enum)
    std::vector<Arg_Type> args;   // List of event-dependant arguments
};

但后来我想把我的各种事件存储在一个载体中:

std::vector<Event*> events;

不幸的是,这似乎并不那么简单!

我将如何实现预期的效果?也就是说,能够传递具有不同种类的参数类型的事件吗?

我知道我可以这样做:

struct Event {};

struct EventFloat : public Event {};

struct EventString : public Event {};

但它似乎不够优雅,难以维持。

1 个答案:

答案 0 :(得分:1)

让您的Event<>课程从公共家长继承,例如EventInterfaceEventInterface将是一个抽象类,用于定义所有事件的接口。

class EventInterface
{
    public:
        virtual void tweak  ( int t ) = 0;
        virtual void twiddle( int t ) = 0;
        virtual void frob   ( int f ) = 0;

        virtual ~EventInterface() {};
};

template <typename Arg_Type> struct Event : public EventInterface {
};

然后将你的矢量设为std::vector<EventInterface *>或类似物。

从维护的角度来看,它并不是那么糟糕,因为所有常见的接口类都为所有要遵守的事件定义了一个公共接口。如果您确实想要添加新的非模板事件类,则可以。

缺点是你无法使ArgType成为公共界面的一部分。但是,这有一定意义:如果你不知道参数的类型,你怎么能合法地在Event*上调用任意方法呢?

现在您可以要求所有Arg_Type都是某些常见EventArgument类的子类,并根据这些类定义您的接口。模板仍会给你买点东西。这完全取决于您希望如何定义事件界面。

工作示例:

class EventArgument 
{
     public:
         virtual int getId () = 0;
         virtual ~EventArgument() { };
};

class EventInterface
{
    public:
        virtual void tweak  ( int t ) = 0;
        virtual void twiddle( int t ) = 0;
        virtual void frob   ( int f ) = 0;
        virtual EventArgument& getArg() = 0;

        virtual ~EventInterface() {};
};

class fredArg   : public EventArgument
{
    public:
    virtual int getId() { return 1; }
    ~fredArg() { };
};
class barneyArg : public EventArgument
{
    public:
    virtual int getId() { return 2; }
    ~barneyArg() { };
};

template <typename Arg_Type>
struct Event : public EventInterface
{

    Arg_Type arg;

    Event() { };

    virtual void tweak  ( int t ) { };
    virtual void twiddle( int t ) { };
    virtual void frob   ( int f ) { };

    virtual EventArgument& getArg()
    {
        return arg;
    }
};

#include <vector>
#include <iostream>

std::vector<EventInterface*> events;

int main()
{
    events.push_back( new Event<fredArg>(  ) );
    events.push_back( new Event<barneyArg>(  ) );

    std::cout << events[0]->getArg().getId() << std::endl;
    std::cout << events[1]->getArg().getId() << std::endl;
}

按照您的预期打印12