代码之家  ›  专栏  ›  技术社区  ›  samuil

如何在基类中声明类工厂的方法?

  •  2
  • samuil  · 技术社区  · 17 年前

    我正在寻找C++类设计问题的解决方案。我试图实现的是在基类中使用静态方法方法,它将返回后代类型对象的实例。关键是,其中一些应该是单件的。我是用VCL写的,所以有可能使用 __properties 但是我更喜欢纯C++解决方案。

    class Base {
      private:
        static Base *Instance;
      public:
        static Base *New(void);
        virtual bool isSingleton(void) = 0;
    }
    Base::Instance = NULL;
    
    class First : public Base { // singleton descendant
      public:
        bool isSingleton(void) { return true; }
    }
    
    class Second : public Base { // normal descendant
      public:
        bool isSingleton(void) { return false; }
    }
    
    Base *Base::New(void) {
      if (isSingleton())
        if (Instance != NULL)
          return Instance = new /* descendant constructor */;
        else
          return Instance;
      else
        return new /* descendant constructor */;
    }
    

    出现的问题:

    • 如何声明静态变量 Instance ,所以它在后代类中是静态的
    • 如何调用基类中的后代构造函数

    我认为按照我的计划去解决这些问题可能是不可能的。如果是这样,我想就如何以其他方式解决这个问题提出一些建议。


    编辑 :代码中的一些细微更改。我在里面漏掉了几个指针。

    4 回复  |  直到 17 年前
        1
  •  4
  •   anon    17 年前

    为了检查我们的术语是否同步,在我的书中,工厂类是一个类实例,它可以创建一些其他类的实例。要创建的实例类型的选择基于工厂接收的输入,或者至少基于工厂可以检查的内容。这是一个非常简单的工厂:

    class A { ~virtual A() {} };   
    class B : public A {};
    class C : public A {};
    
    class AFactory {
       public:
          A * Make( char c ) {
             if ( c == 'B' ) {
                 return new B;
             }
             else if ( c == 'C' ) { 
                return new C;
             }
             else {
               throw "bad type";
             }
          }
    };
    

    如果我是你,我会重新开始,记住这个例子和以下几点:

    • 阶乘不一定是单件的
    • 工厂不必是静态成员
    • 工厂不必是其创建的层次结构的基类的成员
    • 工厂方法通常返回动态创建的对象
    • 工厂方法通常返回指针
    • 工厂方法需要一种方法来决定要创建的实例的类

    我不明白为什么你的工厂需要反思,C++在任何情况下都不支持有意义的方式。

        2
  •  2
  •   1800 INFORMATION    17 年前

    根据@shankdown的答案,我会 Base 在实际类型上模板化,使用 CRTP :

    template <class T>
    class Base
    {
    public:
     static std::auto_ptr<Base<T> > construct()
     {
        return new T();
     }
    };
    
    class First : public Base<First>
    {
    };
    
    class Second : public Base<Second>
    {
    };
    

    这很好,因为 construct 现在再次成为静态成员。你可以这样称呼它:

    std::auto_ptr<First> first(First::construct());
    std::auto_ptr<Second> second(Second::construct());
    
    // do something with first and second...
    
        3
  •  1
  •   Igor    17 年前

    您可以创建一个singleton类和一个nonsingleton类,并使所有后代继承其中一个。

    class Base {
      public:
        static Base *New() = 0;
    }
    
    class SingletonDescendant: public Base { 
      public:
        *Base::New() {
          if (Instance != NULL)
            return Instance = new /* descendant constructor */;
          else
            return Instance;
        }
      private:
        static Base *Instance;
    }
    SingletonDescendant::Instance = NULL;
    
    class NonSingletonDescendant: public Base { 
      public:
        *Base::New() {
          return new;
        }
    }
    
    class First : public SingletonDescendant{ // singleton descendant
    }
    
    class Second : public NonSingletonDescendant{ // normal descendant
    }
    

    它解决了您提出的问题:

    • 如何声明静态变量实例,使其在子类中是静态的: 它只存在于singletonDescendant类中。
    • 如何调用基类中的后代构造函数: 使用新功能
    • 我必须写作 construct() 方法在每个后代中;我认为它是多余的,因为它显然要做什么: 现在它只在单子代和非单子代。
        4
  •  0
  •   Nate W.    17 年前

    像这样的怎么样:

    class Base
    {
    public:
     virtual Base construct() = 0;
    };
    
    class First : public Base
    {
    public:
     Base construct(){ return First(); // or whatever constructor }
    };
    
    class Second : public Base
    {
    public:
     Base construct(){ return Second(...); // constructor }
    };