2009-06-29 35 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