2009-06-29 26 views
2

以下代码是我用于事件派发的简化版本。关键点是 static_cast < T * >对模板仿函数的参数和另一个类使 肯定传递给仿函数的参数是static_cast投给的内容。有没有一个名称管理邪恶的模式static_casts

struct AbstractArg { 
    virtual ~AbstractArg() { } 
}; 

struct AbstractFunctor { 
    virtual void operator()(AbstractArg*) const = 0; 
    virtual ~AbstractFunctor() { } 
}; 


namespace evil { 

template<typename ArgT> 
struct CastingFunctor : AbstractFunctor { 
    void operator()(AbstractArg* aarg) const 
    { 
    ArgT* arg = static_cast<ArgT*>(arg); // Danger! 
    // ... do stuff with it 
    } 
}; 

} // namespace evil 


class TypeidManager 
{ 
public: 
    typedef std::map<std::string, AbstractFunctor*> map_type; 

    void dispatch(AbstractArg* arg) const 
    { 
    map_type::const_iterator it = typeid_map.find(std::string(typeid(*arg).name())); 
    if (it != typeid_map.end()) 
    { 
     AbstractFunctor* pFunctor = it->second; 
     (*pFunctor)(arg); 
    } 
    }; 

    template<typename ArgT> 
    void register_func(void (*fun_ptr)(ArgT*)) 
    { 
    typeid_map.insert(std::make_pair(std::string(typeid(ArgT).name()), 
            new evil::CastingFunctor<ArgT>)); 
    } 

private: 
    map_type typeid_map; 
}; 

是否有这种模式的名称?

谢谢!

+0

您不应该使用.name()的结果进行比较。对于它的内容没有任何保证。更好地将&typeid(ArgT)的结果存储在映射中,并使用比较两个typeid的比较器(首先解除引用的指针)。 – 2009-06-29 16:18:55

+0

为了简单起见,我在这段代码中使用了.name()。真正的代码使用Loki type_info包装器。 – 2009-06-29 18:27:33

回答

3

这不是一种反模式,它是一种非常有用的技术,常用于类型擦除。

0

不是我所知道的,虽然我们在这里使用类似的东西。

1

我认为这是一种反模式,而不是模式。通常,您想通过typeid_map结构向仿函数提供的内容来自共同的继承层次结构,您将使用动态多态性(=虚方法)。基本上你已经重新创建了虚拟方法表查找(以非常低效的方式)。

+0

我大多同意,模式是边界线,但它有它的用处。它的主要优点是你不强制在客户端类上进行任何接口/继承。 – bltxd 2009-06-29 16:10:31