可以在C ++中给出它的类型来实例化对象吗?

时间:2010-11-21 23:07:51

标签: c++ c++11

我用Java编程的时间太长了,找回了一些C ++的方法。我想编写一些给定类的代码(type_info或其在字符串中的名称)可以创建该类的实例。为简单起见,我们假设它只需要调用默认构造函数。这在C ++中是否可行,如果不是,它将来的TR?

我找到了一种方法来做到这一点,但我希望有一些更“动态”的东西。对于我希望实例化的类(这本身就是一个问题,因为我希望将该决定留给配置),我创建了一个单例工厂,其中包含一个静态创建的实例,该实例将自己注册到另一个类。例如。对于类Foo,还有一个具有静态FooFactory实例的FooFactory,因此在程序启动时会调用FooFactory构造函数,该构造函数将自己注册到另一个类。然后,当我希望在运行时创建一个Foo时,我找到了FooFactory并调用它来创建Foo实例。在C ++中做这件事有什么好处吗?我猜我刚刚被Java / C#中的反思所破坏。

对于上下文,我正在尝试将我在Java世界中习惯的一些IOC容器概念应用到C ++中,并希望我可以使它尽可能动态,而无需添加Factory类对于我申请中的其他课程。

4 个答案:

答案 0 :(得分:0)

你可以随时使用模板,但我不确定这是你想要的:

template <typename T>
T
instantiate ()
{
  return T ();
}

或者在课堂上:

template <typename T>
class MyClass
{
  ...
};

答案 1 :(得分:0)

欢迎使用C ++:)

您是正确的,您需要Factory来创建这些对象,但每个文件可能不需要一个Factory

进行此操作的典型方法是让所有可实现的类派生自一个公共基类,我们将调用Base,这样您就需要一个Factory来提供std::unique_ptr<Base> {1}}每次都给你。

有两种方法可以实现Factory

  • 您可以使用Prototype模式,并注册要创建的类的实例,将在其上调用clone函数。
  • 您可以注册指向函数或仿函数的指针(或C ++ 0x中的std::function<Base*()>

当然,难点是动态注册这些条目。这通常在静态初始化期间启动时完成。

// OO-way
class Derived: public Base
{
public:
  virtual Derived* clone() const { return new Derived(*this); }
private:
};

// start-up...
namespace { Base* derived = GetFactory().register("Derived", new Derived); }

// ...or in main
int main(int argc, char* argv[])
{
  GetFactory().register("Derived", new Derived(argv[1]));
}

// Pointer to function
class Derived: public Base {};

// C++03
namespace {
  Base* makeDerived() { return new Derived; }
  Base* derived = GetFactory().register("Derived", makeDerived);
}

// C++0x
namespace {
  Base* derived = GetFactory().register("Derived", []() { return new Derived; });
}

启动方式的主要优点是您可以在自己的文件中完美地定义Derived类,将注册放在那里,并且没有其他文件受到您的更改的影响。这非常适合处理依赖项。

另一方面,如果您要创建的原型需要一些外部信息/参数,那么您将被迫使用初始化方法,最简单的方法是在main中注册您的实例(或等效的) )一旦你有了必要的参数。

快速注意:指向函数方法的指针是最经济的(在内存中)和最快的(在执行中),但语法很奇怪......

关于后续问题。

是的,可以将类型传递给函数,但可能不是直接传递:

  • 如果在编译时知道有问题的类型,你可以使用模板,虽然你需要一些时间来熟悉语法
  • 如果没有,那么您需要传递某种ID并使用工厂方法

如果您需要传递类似于object.class的内容,那么在我看来您正在接近双重调度用例,并且值得查看Visitor模式。

答案 2 :(得分:-1)

没有。没有办法从类型名称到实际类型;丰富的反思非常酷,但几乎总有一种更好的方式。

答案 3 :(得分:-1)

上次我检查过C ++中没有“var”或“dynamic”这样的东西(虽然那是一个WHILE前)。您可以使用(void *)指针然后尝试相应地进行转换。此外,如果内存对我有用,C ++确实有RTTI,它不是反射,但可以帮助在运行时识别类型。