2
#include <memory>

class Base
{
    std::shared_ptr<Base> create() const; // Returns a default constructed object
}

假设所有派生到任何程度的成员Base都是可复制构造和默认构造的。我想要

std::shared_ptr<Base> create() const;

创建适当动态类型对象的方法,但我不想使用样板代码。

是否可以制作

std::shared_ptr<Base> create() const;

静态绑定,但在内部以某种方式找到正确的类型并使用默认构造函数创建对象?可能使用 C++11。

4

2 回答 2

1

这些create()函数可能应该是静态的,因为您还没有实例。但是如果没有参数,你就不能做你想做的事......当然,除非你使用模板:

class Base
{
public:
    template<typename T>
    static std::shared_ptr<Base> create() const
    {
        return std::shared<Base>(new T);
    }
};

然后以这种方式使用它:

std::shared_ptr<Base> ptr(Base::create<Foo>());

或者,如果您愿意:

std::shared_ptr<Base> ptr(Foo::create<Foo>());
于 2012-07-20T19:04:57.480 回答
1

理想情况下,您有一个静态函数,也许还有一个非静态create()函数。有一个聪明的方法可以做到这一点。

  1. 定义一个SuperBase类。它需要一个虚析构函数和一个纯虚create()函数。您将使用指向此类的指针/引用来进行正常的后期绑定 OOP 行为。

  2. 定义一个Base继承自SuperBase. Base的模板参数将是类的类型DerivedBase还将有一个带有静态函数的特征类模板,称为create(). 此静态create()函数将使用new. 使用 trait 的create()函数,Base将定义 astatic_create()和纯虚SuperBase::create()函数。

  3. Derived通过继承来实现Base<Derived>

完成后,如果您知道您使用的是派生类型,那么您可以编写Derived::create()静态创建一个新类型。如果没有,那么您始终可以使用实例的create()方法。多态性没有被破坏,因为SuperBase会有你需要/想要的多态接口——Base<D>只是一个自动定义static_create()create()函数的辅助类,所以你通常不会Base<D>直接使用。

示例代码如下所示:

#include <memory>
#include <iostream>

class SuperBase
{
  public:
    virtual ~SuperBase() = default;
    virtual std::shared_ptr<SuperBase> create() const = 0;
};

template <typename T>
struct Base_Traits
{
  static T* create()
  {
    return new T;
  }
};

template <typename Derived, typename Traits=Base_Traits<Derived>>
class Base : public SuperBase
{
  public:   
    // Define a static factory function...
    static std::shared_ptr<SuperBase> static_create()
    {
      return std::shared_ptr<SuperBase>{Traits::create()};
    }

    // Define pure virtual implementation...
    std::shared_ptr<SuperBase> create() const override
    {
      return static_create();
    }
};

class Derived : public Base<Derived>
{
};

int main()
{
  auto newone = Derived::static_create();  // Type known @ compile time
  auto anotherone = newone->create();      // Late binding; type not known @ compile time
}
于 2012-07-20T19:40:22.973 回答