Factory类的典型C++实现是否有缺陷?

kov*_*rex 4 c++ singleton factory factory-pattern

我需要在C++中实现工厂类,但是当我考虑这个时,我发现了一个我无法解决的大问题,并且我发现,所有工厂实现示例都以同样的方式存在缺陷.我可能是那个错了,但请告诉我原因.

所以这里是简单的"典型"工厂实现,它允许我在不更改Factory类的情况下注册新对象.

//fruit.h
class Fruit
{
protected :
  int count;
public :
  Fruit(int count) : count(count) {}
  virtual void show() = 0;
};

// factory.h
/** singleton factory */
class Factory
{
  typedef Fruit* (*FruitCreateFunction)(int);
  static Factory* factory;
  std::map<std::string, FruitCreateFunction> registeredFruits;
public :
  static Factory& instance()
  {
    if (factory == NULL)
      factory = new Factory();
    return *factory;
  }
  bool registerFruit(const std::string& name, Fruit* (createFunction)(int))
  {
    registeredFruits.insert(std::make_pair(name, createFunction));
    return true;
  }
  Fruit* createFruit(const std::string& name, int count)
  {
    return registeredFruits[name](count);
  }
};

//factory.cpp
Factory* Factory::factory = NULL;

//apple.h
class Apple : public Fruit
{
  static Fruit* create(int count) { return new Apple(count); }
  Apple(int count) : Fruit(count) {}
  virtual void show() { printf("%d nice apples\n", count); };  
  static bool registered;
};

// apple.cpp
bool Apple::registered = Factory::instance().registerFruit("apple", Apple::create);

//banana.h
class Banana : public Fruit
{
  static Fruit* create(int count) { return new Banana(count); }
  Banana(int count) : Fruit(count) {}
  virtual void show() { printf("%d nice bananas\n", count); };  
  static bool registered;
};

// banana.cpp
bool Banana::registered = Factory::instance().registerFruit("banana", Banana::create);

// main.cpp
int main(void)
{
  std::vector<Fruit*> fruits;
  fruits.push_back(Factory::instance().createFruit("apple", 10));
  fruits.push_back(Factory::instance().createFruit("banana", 7));
  fruits.push_back(Factory::instance().createFruit("apple", 6));
  for (size_t i = 0; i < fruits.size(); i++)
    {
      fruits[i]->show();
      delete fruits[i];
    }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

好吧,这段代码看起来很花哨而且很有效,但是接下来是:

C++标准不允许我定义全局(静态)变量的定义顺序.

我这里有3个静态变量

Apple::registered;
Banana::registered;
Factory::factory;
Run Code Online (Sandbox Code Playgroud)

Factory::factory指针需要被定义为NULL 之前苹果(或香蕉)::注册变量,或所述Factory::instance方法将未初始化值工作,和行为异常.

那么,我到底在哪里?代码真的只是偶然发生了吗?如果是这样,我该如何解决这个问题呢?

Soa*_*Box 11

在任何初始化程序运行之前,所有全局POD数据都保证初始化为常量值.

因此,在程序开始时,在进行任何寄存器调用之前和main运行之前,指针为NULL并且所有bool都自动为假.然后运行初始化程序,包括您的注册调用.

编辑:具体来说,从标准(3.6.2.2:非本地对象的初始化):

零初始化和常量初始化一起称为静态初始化; 所有其他初始化是动态初始化.在进行任何动态初始化之前,应执行静态初始化.