C++ 如何动态创建类对象?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4007382/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:15:45  来源:igfitidea点击:

How to create class objects dynamically?

c++oopdynamic

提问by Nebort

Let's say I have a class box, and a user can create boxes. How to do it? I understand I create objects by className objectName(args);but how to do it dynamically, depending on the user input?

假设我有一个类box,并且用户可以创建box。怎么做?我知道我创建对象的方式是,className objectName(args);但如何根据用户输入动态创建对象?

回答by Patrick

The correct answer depends on the number of different classes of which you want to create the instances.

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

If the number is huge (the application should be able to create an instance of any class in your application), you should use the reflection functionality of .Net. But, to be honest, I'm not a big fan of using reflection in business logic, so I would advise not to do this.

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

I think that in reality you have a limited number on classes for which you want to create instances. And all the other answers make this assumption. What you actually need is a factory pattern. In the next code I also assume that the classes of which you want to create instances, all derive from the same base class, let's say Animal, like this:

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

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

Then create an abstract factory which is an interface that creates an animal:

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

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

Then create subclasses for each of the different kinds of animals. E.g. for the Dog class this will become this:

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

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

And the same for the cat.

猫也一样。

The DogFactory::create method overrules the IFactory::create method, even if their return type is different. This is what is called co-variant return types. This is allowed as long as the return type of the subclass's method is a subclass of the return type of the base class.

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

What you can now do is put instances of all these factories in a map, like this:

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

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

After the user input, you have to find the correct factory, and ask it to create the instance of the animal:

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

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

This is the typical abstract factory approach. There are other approaches as well. When teaching myself C++ I wrote a small CodeProject article about it. You can find it here: http://www.codeproject.com/KB/architecture/all_kinds_of_factories.aspx.

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

Good luck.

祝你好运。

回答by Ton van den Heuvel

The following factory method creates Boxinstances dynamically based on user input:

以下工厂方法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;
    }
};

Of course, PrettyBigBoxand SmallBoxboth derive from Box. Have a look at the creational patterns in the C++ design patterns wikibook, as one of them probably applies to your problem.

当然,PrettyBigBoxSmallBox两个从获得Box。查看C++ design patterns wikibook中的创建模式,因为其中之一可能适用于您的问题。

回答by Michael Aaron Safyan

In C++, it is possible to allocate objects using automatic (stack) and dynamic (heap) storage.

在 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.

You can use pointers and heap-allocation to dynamically construct objects as in:

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

#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;
}

Related: the "Factory" object-oriented design pattern

相关:“工厂”面向对象设计模式