从动态类型信息创建一个新对象

在C ++中,是否有任何方法可以查询对象的类型,然后使用该信息动态创建相同类型的新对象?

例如,假设我有一个简单的3类层次结构:

class Base
class Foo : public Base
class Bar : public Base

现在假设我给你一个类型为Base的对象 - 这是Foo类型的实际。 有没有办法查询类型并使用该信息以稍后创建Foo类型的新对象?


克隆方法

查询类型的语言没有提供任何东西,并且可以根据这些信息构造,但是您可以通过各种方式为类的层次结构提供功能,其中最简单的方法是使用虚拟方法:

struct Base {
  virtual ~Base();
  virtual std::auto_ptr<Base> clone(/*desired parameters, if any*/) const = 0;
};

这有些不同:克隆当前对象。 这通常是您想要的,并允许您将对象保留为模板,然后根据需要进行克隆和修改。

通过扩展Tronic,您甚至可以生成克隆功能。

为什么auto_ptr? 因此,您可以使用new来分配对象,明确所有权的转移,并且调用者确信删除必须释放它。 例如:

Base& obj = *ptr_to_some_derived;
{ // since you can get a raw pointer, you have not committed to anything
  // except that you might have to type ".release()"
  Base* must_free_me = obj.clone().release();
  delete must_free_me;
}
{ // smart pointer types can automatically work with auto_ptr
  // (of course not all do, you can still use release() for them)
  boost::shared_ptr<Base> p1 (obj.clone());
  auto_ptr<Base>          p2 (obj.clone());
  other_smart_ptr<Base>   p3 (obj.clone().release());
}
{ // automatically clean up temporary clones
  // not needed often, but impossible without returning a smart pointer
  obj.clone()->do_something();
}

对象工厂

如果您希望完全按照您的要求进行操作,并获得可独立于实例使用的工厂:

struct Factory {}; // give this type an ability to make your objects

struct Base {
  virtual ~Base();
  virtual Factory get_factory() const = 0; // implement in each derived class
    // to return a factory that can make the derived class
    // you may want to use a return type of std::auto_ptr<Factory> too, and
    // then use Factory as a base class
};

大部分相同的逻辑和功能可用于克隆方法,因为get_factory执行相同角色的一半,并且返回类型(及其含义)是唯一的区别。

我已经有几次涉及工厂了。 你可以调整我的SimpleFactory类,使你的工厂对象(由get_factory返回)持有对全局工厂的引用以及要传递的参数(例如类的注册名称 - 考虑如何将boost :: function和boost :: bind应用到使这个易于使用)。


通过基类创建对象副本的常用方法是添加一个克隆方法,该方法本质上是一个多态复制构造函数。 这个虚函数通常需要在每个派生类中定义,但是您可以通过使用奇怪循环模板模式来避免一些复制和粘贴:

// Base class has a pure virtual function for cloning
class Shape {
public:
    virtual ~Shape() {} // Polymorphic destructor to allow deletion via Shape*
    virtual Shape* clone() const = 0; // Polymorphic copy constructor
};
// This CRTP class implements clone() for Derived
template <typename Derived> class Shape_CRTP: public Shape {
public:
    Shape* clone() const {
        return new Derived(dynamic_cast<Derived const&>(*this));
    }
};
// Every derived class inherits from Shape_CRTP instead of Shape
// Note: clone() needs not to be defined in each
class Square: public Shape_CRTP<Square> {};
class Circle: public Shape_CRTP<Circle> {};
// Now you can clone shapes:
int main() {
    Shape* s = new Square();
    Shape* s2 = s->clone();
    delete s2;
    delete s;
}

请注意,您可以使用相同的CRTP类来实现任何派生类中相同的功能,但需要知道派生类型。 除了clone(),还有其他许多用途,例如双派。


只有一些黑客的方法可以做到这一点。

第一个和最丑陋的是:

Base * newObjectOfSameType( Base * b )
{
  if( dynamic_cast<Foo*>( b ) ) return new Foo;
  if( dynamic_cast<Bar*>( b ) ) return new Bar;
}

请注意,只有启用了RTTI并且Base包含一些虚拟功能时,这才会起作用。

第二个更整洁的版本是为基类添加一个纯虚拟克隆函数

struct Base { virtual Base* clone() const=0; }
struct Foo : public Base { Foo* clone() const { return new Foo(*this); }
struct Bar : public Base { Bar* clone() const { return new Bar(*this); }

Base * newObjectOfSameType( Base * b )
{
  return b->clone();
}

这很干净。

关于这个的一个很酷/有趣的事情是Foo::clone返回一个Foo* ,而Bar::clone返回一个Bar* 。 您可能会期望这会破坏事情,但一切都可以使用,这是由于C ++的一个称为协变返回类型的特性。

不幸的是,协变返回类型不适用于智能指针,所以使用sharted_ptrs你的代码看起来像这样。

struct Base { virtual shared_ptr<Base> clone() const=0; }
struct Foo : public Base { shared_ptr<Base> clone() const { return shared_ptr<Base>(new Foo(*this) ); }
struct Bar : public Base { shared_ptr<Base> clone() const { return shared_ptr<Base>(new Bar(*this)); }

shared_ptr<Base> newObjectOfSameType( shared_ptr<Base> b )
{
  return b->clone();
}
链接地址: http://www.djcxy.com/p/72899.html

上一篇: Creating a new object from dynamic type info

下一篇: segmentation fault in overloading operator =