【问题标题】:How to create class objects dynamically?如何动态创建类对象?
【发布时间】:2011-04-29 18:34:16
【问题描述】:

假设我有一个类box,用户可以创建boxes。怎么做?我知道我通过className objectName(args); 创建对象,但如何根据用户输入动态地创建对象?

【问题讨论】:

  • 你能给出一个(可能是伪代码)代码示例吗?
  • 在哪里创建它们?例如,您可以将它们存储在 std::vector 中,但这实际上取决于您在做什么。
  • 不幸的是,在 c++ 中,您不能动态调用构造函数。唯一的方法是存储能够在运行时返回您想要的新构造对象的对象。您已经收到的示例答案是完全相关的。

标签: c++ oop dynamic


【解决方案1】:

以下工厂方法根据用户输入动态创建Box 实例:

class BoxFactory
{
  public:
    static Box *newBox(const std::string &description)
    {
      if (description == "pretty big box")
        return new PrettyBigBox;
      if (description == "small box")
        return new SmallBox;
      return 0;
    }
};

当然,PrettyBigBoxSmallBox 都派生自 Box。查看C++ design patterns wikibook 中的创建模式,因为其中一个可能适用于您的问题。

【讨论】:

    【解决方案2】:

    在 C++ 中,可以使用自动(堆栈)和动态(堆)存储来分配对象。

    Type variable_name; // variable_name has "automatic" storage.
                        // it is a local variable and is created on the stack.
    
    Type* pointer_name = NULL; // pointer_name is a "pointer". The pointer, itself,
                               // is a local variable just like variable_name
                               // and is also created on the stack. Currently it
                               // points to NULL.
    
    pointer_name = new DerivedType; // (where DerivedType inherits from Type). Now
                                    // pointer_name points to an object with
                                    // "dynamic" storage that exists on the heap.
    
    delete pointer_name; // The object pointed-to is deallocated.
    pointer_name = NULL; // Resetting to NULL prevents dangling-pointer errors.
    

    您可以使用指针和堆分配来动态构造对象,如下所示:

    #include <cstdlib>
    #include <iostream>
    #include <memory>
    class Base {
        public:
            virtual ~Base(){}
            virtual void printMe() const = 0;
        protected:
            Base(){}
    };
    class Alpha : public Base {
         public:
            Alpha() {}
            virtual ~Alpha() {}
            virtual void printMe() const { std::cout << "Alpha" << std::endl; }
    };
    class Bravo : public Base {
         public:
            Bravo() {}
            virtual ~Bravo() {}
            virtual void printMe() const { std::cout << "Bravo" << std::endl; }
    };
    int main(int argc, char* argv[]) {
        std::auto_ptr<Base> pointer; // it is generally better to use boost::unique_ptr,
                                     // but I'll use this in case you aren't familiar
                                     // with Boost so you can get up and running.
        std::string which;
        std::cout << "Alpha or bravo?" << std::endl;
        std::cin >> which;
        if (which == "alpha") {
            pointer.reset(new Alpha);
        } else if (which == "bravo") {
            pointer.reset(new Bravo);
        } else {
            std::cerr << "Must specify \"alpha\" or \"bravo\"" << std::endl;
            std::exit(1);
        }
        pointer->printMe();
        return 0;
    }
    

    相关:the "Factory" object-oriented design pattern

    【讨论】:

      【解决方案3】:

      正确答案取决于您要为其创建实例的不同类的数量。

      如果数量很大(应用程序应该能够在您的应用程序中创建任何类的实例),您应该使用 .Net 的反射功能。但是,老实说,我不太喜欢在业务逻辑中使用反射,所以我建议不要这样做。

      我认为实际上您想要为其创建实例的类数量有限。所有其他答案都做出了这个假设。您真正需要的是工厂模式。在接下来的代码中,我还假设您要为其创建实例的类都派生自同一个基类,比如说 Animal,如下所示:

      class Animal {...};
      class Dog : public Animal {...}
      class Cat : public Animal {...}
      

      然后创建一个抽象工厂,它是一个创建动物的接口:

      class IFactory
         {
         public:
            Animal *create() = 0;
         };
      

      然后为每种不同种类的动物创建子类。例如。对于 Dog 类,这将变为:

      class DogFactory : public IFactory
         {
         public:
            Dog *create() {return new Dog();}
         };
      

      猫也是如此。

      DogFactory::create 方法优先于 IFactory::create 方法,即使它们的返回类型不同。这就是所谓的协变返回类型。只要子类方法的返回类型是基类的返回类型的子类,这是允许的。

      您现在可以将所有这些工厂的实例放入地图中,如下所示:

      typedef std::map<char *,IFactory *> AnimalFactories
      AnimalFactories animalFactories;
      animalFactories["Dog"] = new DogFactory();
      animalFactories["Cat"] = new CatFactory();
      

      用户输入后,你必须找到正确的工厂,并要求它创建动物的实例:

      AnimalFactories::const_iterator it=animalFactories.find(userinput);
      if (it!=animalFactories.end())
         {
         IFactory *factory = *it;
         Animal *animal = factory->create();
         ...
         }
      

      这是典型的抽象工厂方法。 还有其他方法。在自学 C++ 时,我写了一篇关于它的 CodeProject 小文章。你可以在这里找到它:http://www.codeproject.com/KB/architecture/all_kinds_of_factories.aspx

      祝你好运。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-25
        • 1970-01-01
        • 1970-01-01
        • 2023-03-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多