2

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

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

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

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

我需要这样的功能:

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

派生类的数量是可变的,我不想进行诸如name手动切换和返回新对象类型之类的事情。无论如何,C++ 中是否有可能自动执行此操作?

ps 用法应该如下所示:

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

我需要纯 c++ 代码(跨平台)。使用 boost 是允许的。

4

6 回答 6

2

在 C++ 中不可能做到这一点。

一种选择是编写工厂并打开传入的名称,但我看到您不想这样做。除了 dynamic_cast 之外,C++ 没有提供任何真正的运行时反射支持,所以这类问题很难解决。

于 2011-01-16T11:51:02.560 回答
2

有一个很好的技巧,它允许你编写一个没有if...else if....

(请注意,AFAIK,确实不可能在 C++ 中做你想做的事,因为这段代码是在编译时生成的。为此目的存在“工厂方法”设计模式)

首先,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为每个子类实现。

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

于 2011-01-16T12:41:53.593 回答
0

是的,这是可能的!检查这个非常有趣的类,您可以通过并且甚至可以提供参数列表Activator 来创建所有内容,因此该方法将使用最佳参数集调用适当的构造函数。Typestring

于 2011-01-16T11:45:20.053 回答
0

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

于 2011-01-16T11:49:43.400 回答
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);
}
于 2011-01-16T12:07:33.390 回答
0

C++ 不支持反射

在我看来,这是 Java 击败 C++ 的单点。
(不要为此获得太多反对票......)

您可以通过使用自定义预处理器来实现类似的效果,类似于 MOC 为 Qt 所做的事情。

于 2011-01-16T12:24:39.420 回答