如何动态创建类对象?

时间:2010-10-24 07:14:49

标签: c++ oop dynamic

假设我有一个类,用户可以创建。怎么做?我理解我是按className objectName(args);创建对象但是如何根据用户输入动态创建对象?

4 个答案:

答案 0 :(得分:19)

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

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

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

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

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

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

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

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

祝你好运。

答案 1 :(得分:5)

以下工厂方法根据用户输入动态创建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 :(得分:3)

在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 :(得分:0)

一种简单的方法是使用矢量。 首先,包含矢量库并将临时对象作为您的类。

class temp;

然后,使用您的类类型创建一个矢量,例如命名对象:

#include <vector>
.
.
vector <class>objects;

然后你可以添加一个循环来添加一个对象。例如,我有一个名为temp的类,它有一个名为input的函数,我想添加:

while(1){
        temp.input();
        objects.push_back(temp);
        }

现在你有一个动态类。 要访问您的对象,您可以这样使用:

objects[i];

如果你想删除一个对象,只需使用这种方式: 1.在向量中找到您的对象位置。 2.用它改变向量的最后一个块的数量并删除最后一个块:

objects[location of the object you want to remove]=objects[location of your last block];
objects.pop_back();

如果你想知道矢量最后一个块的位置,请执行以下操作:

int lastblock;
lastblock=(objects.size()-1);

注意:您可以使用数组之类的矢量。