2016-06-08 80 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

相关问题