【问题标题】:How can I instantiate an object knowing only its name? [duplicate]如何实例化只知道其名称的对象? [复制]
【发布时间】:2012-01-06 08:31:19
【问题描述】:

可能重复:
Is there a way to instantiate objects from a string holding their class name?

在 C++ 中,我想让我的用户输入要在运行时创建的对象类型名称,并且根据我从他们那里得到的字符串,程序将实例化正确的对象(简而言之,我实现工厂方法模式)。但是,如果程序必须支持新的对象类型,则不允许修改现有代码。

那么是否有可能从方法中删除所有 if...else if...else if... 东西,并且仍然让我的程序实例化特定产品类型的正确对象(在众多对象中,只有在编译时才知道)?

我四处搜索找到了这个链接:Is there a way to instantiate objects from a string holding their class name? ,这似乎是我想要的,但我根本看不懂代码。

任何帮助将不胜感激。

【问题讨论】:

  • @CharlesB 你不需要反射,你可以使用工厂。
  • @LuchianGrigore:工厂是一种设计模式,反射是一种语言特性。如果您想要一个没有 if..else..else... 的工厂,您需要一种具有反射的语言或二进制插件架构,就像 Alessandro 的回答中一样

标签: c++ class reflection instantiation


【解决方案1】:

这只有在所有必需的类都派生自某个公共基类时才有效,并且您通常只能使用基接口(尽管您可以通过一些额外的努力来解决这个问题)。这是一种方法:

// Immutable core code:

#include <map>
#include <string>

class Base
{
  typedef Base * (*crfnptr)(const std::string &);
  typedef std::map<std::string, crfnptr> CreatorMap;

  static CreatorMap creators;

public:
  virtual ~Base() { }
  Base * clone() const { return new Base(*this); }

  static Base * create_from_string(std::string name)
  {
    CreatorMap::const_iterator it = creators.find(name);
    return it == creators.end() ? NULL : it->first();
  }

  static void register(std::string name, crfnptr f)
  {
    creators[name] = f;
  }
};

现在您可以从新代码中添加新的派生类:

// your code:

#include "immutable_core.hpp"

class Foo : public Base
{
public:
  Foo * clone() const { return new Foo(*this); }
  static Foo * create() { return new Foo; }
};

Base::register("Foo", &Foo::create);

要创建一个类,您只需调用Base * p = Base::create_from_string("Foo");。

【讨论】:

  • 这里需要clone() 函数吗?我不确定去掉它们是否是个好主意。
  • @Daan:你说得对,工厂本身不需要它们,但在你不知道对象的最衍生类型的情况下,它们充当复制构造函数的角色,所以它们在主题上是相关的。
  • 所以如果我理解正确的话,我需要它们从Base* 到Derived* 的无缝转换?
  • @Daan:不,一点也不。您需要它们来复制您从工厂获得的对象。
  • 好的,谢谢 :) 我尽量避免复制,所以我就把它删掉了。
【解决方案2】:

您可以实现类似插件系统的功能。我已经用dlopen 在Linux 中实现了这个。程序无需修改,只需添加新类作为动态库,将在运行时加载。

您可以从这里开始了解更多信息:C++ dlopen mini HOWTO

【讨论】:

    猜你喜欢
    • 2015-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多