我对泛型编程几乎没有经验(我很少需要它),但我现在正在尝试为我的应用程序实现一个事件系统。这就是我对实际事件的想法:
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 {};
但它似乎不够优雅,难以维持。
答案 0 :(得分:1)
让您的Event<>
课程从公共家长继承,例如EventInterface
。 EventInterface
将是一个抽象类,用于定义所有事件的接口。
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;
}
按照您的预期打印1
和2
。