假设我有一个名为box的类,用户可以创建boxes。如何实现呢?我知道通过className objectName(args);
来创建对象,但如何根据用户输入动态地创建对象呢?
正确答案取决于您要创建实例的不同类别数量。
如果数量很大(应用程序应能够创建应用程序中的任何类的实例),则应使用.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。
祝好运。
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;
}
};
PrettyBigBox
和SmallBox
都是从Box
派生而来。请查看C++设计模式wikibook中的创建型模式,其中一个可能适用于您的问题。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;
}
相关内容:"工厂"面向对象设计模式
std::vector
中,但这实际上取决于您正在做什么。 - GManNickG