如果你真的不想使用虛擬功能(這似乎是一個完美的使用情況下,爲他們真正的,但我不知道你的消息類),您可以使用CRTP:
template <typename U>
struct Consumer
{
template <typename T>
void callback(T msg)
{ static_cast<U*>(this)->callback(msg); }
};
struct Client : Consumer<Client>
{
void callback(Msg1 msg);
void callback(Msg2 msg);
void callback(Msg3 msg);
};
的問題,當然,是你不能存儲在一個容器中的任何更Consumer
對象。由於一切都是編譯時間,所以客戶端的實際類型必須與消費者對象一起存儲,供編譯器調用正確的回調函數。虛擬功能可以讓你等待直到運行這個...
是否有一個原因沒有Msg
類多態和使用標準的虛擬功能(除「我必須重寫所有的代碼,我不能」)?
編輯如果你擔心的是消息類,爲什麼不使用類似的東西,假設消息類實現DoSomething
成員函數:(這個技術被稱爲類型擦除)
struct AnyMsg
{
template <typename Msg>
AnyMsg(Msg x) : impl(newImpl(x)) {}
void DoSomething() { impl->DoSomething(); }
private:
struct Impl
{
virtual ~Impl() {}
virtual void DoSomething() = 0;
};
// Probably better is std::unique_ptr if you have
// C++0x. Or `boost::scoped_ptr`, but you have to
// provide copy constructors yourself.
boost::shared_ptr<Impl> impl;
template <typename Msg>
Impl* newImpl(Msg m)
{
class C : public Impl
{
void DoSomething() { x.DoSomething(); }
Msg x;
public:
C(Msg x) : x(x) {}
};
return new C(m);
}
};
你可以自定義newImpl
的行爲以得到你想要的東西(例如,如果消息類中沒有成員函數,某些消息類或其他任何東西沒有專門化,則默認操作)。這樣,您就可以實現Msg
類,就像您使用模板解決方案所做的那樣,並且您擁有一個可以傳遞到客戶類中的虛擬函數的獨特外觀。
如果Message類將會有很大的不同,並且客戶端類可能會對它們做出不同的反應,並且您將有很多消息類,這會開始聞起來。或者也許你有一個醜陋可怕的候選人Visitor pattern。
他是什麼虛擬功能 – KitsuneYMG 2011-02-02 09:29:11
虛擬功能不是我關心的;它爲每個可能的消息類都重載。 – Graeme 2011-02-02 09:34:27
你可以讓msg多態 - 以及擺脫模板?你有多少個msg類? – Anycorn 2011-02-02 09:40:06