在对象工厂中注册对象创建者

boc*_*cco 2 c++ implementation design-patterns visual-c++

我有方便的对象工厂模板,它按类型ID名称创建对象.实现非常明显:ObjectFactory包含从std::string对象创建者函数的映射.然后,所有要创建的对象都应在此工厂中注册.

我使用以下宏来做到这一点:

#define REGISTER_CLASS(className, interfaceName) \
   class className; \
   static RegisterClass<className, interfaceName> regInFactory##className; \
   class className : public interfaceName
Run Code Online (Sandbox Code Playgroud)

这里RegisterClass

   template<class T, class I>
   struct RegisterClass
   {
      RegisterClass()
      {
         ObjectFactory<I>::GetInstance().Register<T>();
      }
   };
Run Code Online (Sandbox Code Playgroud)

用法

class IFoo
{
public:
   virtual Do() = 0;
   virtual ~IFoo() {}
}

REGISTER_CLASS(Foo, IFoo)
{
   virtual Do() { /* do something */ }
}

REGISTER_CLASS(Bar, IFoo)
{
   virtual Do() { /* do something else */ }
}
Run Code Online (Sandbox Code Playgroud)

类在工厂中同时定义和注册.

问题是regInFactory...静态对象是在.h文件中定义的,因此它们将被添加到每个翻译单元中.同一个对象创建者将被多次注册,更重要的是,会有很多具有静态存储持续时间的冗余对象.

有没有办法做这样优雅的注册(不是复制/粘贴类和接口名称),但是不要在全球范围内传播冗余的静态对象?

如果一个好的解决方案需要一些VC++特定的扩展(不符合C++标准),我会很好.

APr*_*mer 5

所以你想把变量定义放在头文件中?有一种可移植的方式:模板类的静态变量.所以我们得到:

template <typename T, typename I>
struct AutoRegister: public I
{
    // a constructor which use ourRegisterer so that it is instantiated; 
    // problem catched by bocco
    AutoRegister() { &ourRegisterer; } 
private:
    static RegisterClass<T, I> ourRegisterer;
};

template <typename T, typename I>
RegisterClass<T, I> AutoRegister<T, I>::ourRegisterer;

class Foo: AutoRegister<Foo, IFoo>
{
public:
    virtual void Do();         
};
Run Code Online (Sandbox Code Playgroud)

请注意,我保留了IFoo非虚拟的继承.如果有多次从该类继承的风险,它应该是虚拟的.