2012-07-20 107 views
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。

+1

的模板?'template std :: shared_ptr create()const {return new T(); }; p =创建();'。也许你可以提供一个如何使用它的例子? – 2012-07-20 19:03:37

+2

你在做什么*做*? – rubenvb 2012-07-20 19:07:28

+0

大图中,我试图创建一个函数,它接受一个字符串形式的类名,并返回一个std :: shared_ptr 和相应的动态类型。我想实现这个使用静态std :: map 对象 – 2012-07-20 19:11:33

回答

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>()); 
+0

谢谢!其实我有一个例子。我有一个std :: shared_ptr 对象,它指向一个可能与Base不同的动态类型的对象。使用这个指针我想要求一个默认构造的适当动态类型的样本。 – 2012-07-20 19:16:41

+0

虽然这个答案不是我正在寻找的,但我相信Ben Voigt,这是不可能的。我会照你说的去做。它实际上解决了我的问题。 – 2012-07-20 19:22:01

+0

@Martin:我会争辩说,这个答案并没有让你到任何地方。如果你知道你想创建的类型,那么你可以很容易地创建shared_ptr --why调用一个函数?即使使用这个函数,你也需要指定两个类型:一个是前一个:: create和模板参数。呃,因为它不需要!当你不知道除抽象基类以外的任何类型时,我会认为你还想处理一般情况 - 对于这样的答案(分别),它们的用处不大。例如,你如何使用迭代器调用create()来列出>? – 2012-07-20 20:13:05

1

理想情况下,您有一个静态的或者非静态的create()函数。有一个聪明的方法来实现这一点。

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

  2. 定义从SuperBase继承的Base类模板。 Base的模板参数将是Derived类的类型。 Base也将具有一个名为create()的具有静态函数的特征类模板。这个静态的create()函数将创建一个默认对象new。使用特征的create()函数Base将定义static_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 
} 
+0

谢谢!我很欣赏你的方法! – 2012-07-24 21:12:18

相关问题