按名称创建对象

时间:2011-01-16 11:41:45

标签: c++ class object creation

是否可以在c ++中使用传递的类型名称(字符串)返回对象的示例? 我有一些基本的抽象类Base和一些派生。示例代码:

class Base
{
   /* ... */
};

class Der1 : public Base
{
   /* ... */
};

class Der2 : public Base
{
   /* ... */
};

我需要以下功能:

Base *objectByType(const std::string &name);

派生类的数量是可变的,我不想做像name的切换和手动返回新对象类型。是否有可能在c ++中自动执行此操作?

P.S。用法应如下:

dynamic_cast<Der1>(objectByType("Der1"));

我需要纯c ++代码(跨平台)。允许使用提升。

6 个答案:

答案 0 :(得分:2)

在C ++中无法做到这一点。

一个选项是写一个工厂并打开传入的名称,但我发现你不想这样做。除了dynamic_cast之外,C ++不提供任何真正的运行时反射支持,因此这类问题很难解决。

答案 1 :(得分:2)

有一个很好的技巧,可以让你编写一个factory method而不需要if...else if...的序列。

(请注意,AFAIK,确实不可能在C ++中执行您想要的操作,因为此代码是在编译时生成的。为此目的存在“工厂方法”Design Pattern

首先,为派生类定义global repository。它可以采用std::map<std::string, Base*>的形式,即将派生类的名称映射到该类的an instance

对于每个派生类,您定义一个default constructor,它将该类的对象添加到类名下的存储库中。您还可以定义类的静态实例:

// file: der1.h
#include "repository.h"

class Der1: public Base {
public:
  Der1() { repository[std::string("Der1")] = this; }
};

// file: der1.cpp
static Der1 der1Initializer;

静态变量的构造函数甚至在main()之前运行,因此当您的main启动时,您已经使用所有派生类的实例初始化了存储库。

您的工厂方法(例如Base::getObject(const std::string&))需要在存储库映射中搜索类名。然后,它使用它找到的对象的clone()方法来获取相同类型的新对象。您当然需要为每个子类实现clone

这种方法的优点是,当您添加新的派生类时,您的添加仅限于实现新类的文件。存储库和工厂代码不会更改。当然,您仍需要重新编译程序。

答案 2 :(得分:0)

是的,这是可能的!检查一个名为Activator的非常有趣的课程 您可以按Typestring创建所有内容,甚至可以提供参数列表,因此该方法将使用最佳参数集调用相应的构造函数。

答案 3 :(得分:0)

除非我误解,否则typeid关键字应该是您要查找的内容的一部分。

答案 4 :(得分:0)

这是不可能的。您必须自己编写objectByType函数:

Base* objectByType(const std::string& name) {
  if (name == "Der1")
    return new Der1;
  else if (name == "Der2")
    return new Der2;
  // other possible tests
  throw std::invalid_argument("Unknown type name " + name);
}

答案 5 :(得分:0)

C ++不支持reflection

在我看来,这是Java击败C ++的唯一方面 (请不要为此投票太多......)

你可以通过使用自定义预处理器来实现类似的功能,类似于MOC对Qt的处理方式。