2016-06-08 40 views
1

我必須創建許多業務對象(每個客戶端都應該獲得它自己的類)。理想情況下,我希望能夠通過客戶端內部標籤(即Client::getName(void))訪問該類,因此我創建了一個實現此目的的宏。創建一個類名作爲模板參數的類

#define CLIENT_CLASS(classname) \ 
class classname : public Base \ 
{ \ 
public: \ 
    classname(void); \ 
    ~classname(void) {}; \ 
public: \ 
    static const std::string name; \ 
    static ClientId ID(void) { return CID_##classname; } \ 
    static Base *createInstance(void) { return new classname(); } \ 
private: \ 
    typedef Base super; \ 
} 

本來我複製這是每個類seperately,但當然我想擁有的東西,在需要時可以進行編輯。我寧願將它作爲模板實現,但我不確定這是否可能,因爲我沒有看到任何方式來指定模板中的類名,而AFAIK也無法在模板中定義靜態方法?或者我錯了,確實有辦法將其轉換爲適當的模板?

CLIENT_CLASS_BODY是bascially看起來像另一個的另一個宏,但包含了公共類體的定義(如果可以對它進行模板化,可以將其移到模板中)。

工廠看起來是這樣的:

包括

namespace va { 
    CLIENT_CLASS(client1); 
    CLIENT_CLASS(client2); 
    .... 
} 

CPP

namespace va { 
    CLIENT_CLASS_BODY(client1); 
    CLIENT_CLASS_BODY(client2); 
    ... 
} 

#define CREATE_CLIENT(classname) addKey(classname::name, classname::ID(), classname::createInstance()) 

void ClientFactory::initClientMap(void) 
{ 
    CREATE_CLIENT(va::client1); 
    CREATE_CLIENT(va::client2); 
    ... 
} 
+0

呦你可以在模板類中定義靜態成員函數。 – 101010

+0

C++概念不符合這個想法(如Java或C#),沒有「類對象」。如果你想改變功能初始化一個類與參考(指針)不同的「實現對象」 –

+2

你對靜態方法的使用看起來很奇怪。你只能通過給出類名來調用它們 - 然後它們返回它。這有什麼意義?你不能用'static'方法來做多態。 –

回答

0

有了模板,它應該看起來像這樣的:

template <ClientId Id, const char* Name> 
class TClient : public Base 
{ 
public: 
    TClient() {} 
    ~TClient() {} 
public: 
    static const std::string name; 
    static ClientId ID() { return Id; } 
    static Base *createInstance() { return new TClient(); } 
private: 
    using super = Base; 
}; 

template<ClientId Id, const char* Name> const std::string TClient<Id, Name>::name = Name; 

然後

static constexpr char Client1Name[] = "Client1"; 
using Client1 = TClient<1, Client1Name>; 

Demo

以同樣的方式,

#define CREATE_CLIENT(classname) addKey(classname::name, classname::ID(), classname::createInstance()) 

應該

template <typename T> 
void ClientFactory::CreateClient() 
{ 
    addKey(T::name, T::ID(), T::createInstance()); 
} 

然後

void ClientFactory::initClientMap() 
{ 
    CreateClient<va::client1>(); 
    CreateClient<va::client2>(); 
    //... 
} 
+0

基於上述評論,我改變了我的設計,現在只使用了一個基類。我放棄了爲每個客戶端設置一個類名的要求,因爲我認爲使用這個工廠幾乎是一樣的。但是,您的解決方案非常酷。 :) 謝謝! – Devolus

相關問題