将make_shared与受保护的构造函数+抽象接口一起使用

Rob*_*son 5 c++ constructor protected visual-c++-2010 make-shared

给定一个抽象接口和从该接口派生的实现,其中构造函数受到保护(这些对象的创建只能从类工厂中获得 - 实现DI模式),如何在工厂函数中使用make_shared?

例如:

class IInterface
{    
public:    
    virtual void Method() = 0;
};

class InterfaceImpl : public IInterface
{
public:
    virtual void Method() {}

protected:    
    InterfaceImpl() {}    
};

std::shared_ptr<IInterface> Create()
{
    std::shared_ptr<IInterface> object = std:: make_shared<InterfaceImpl>();    
    return object;
}
Run Code Online (Sandbox Code Playgroud)

make_shared显然无法访问InterfaceImpl中的受保护构造函数,或者实际上是在IInterface中,给出了以下错误


error C2248: 'InterfaceImpl::InterfaceImpl' : cannot access protected member declared in class 'InterfaceImpl'
Run Code Online (Sandbox Code Playgroud)

所以在这里阅读(问题:如何使boost :: make_shared成为我班级的朋友),我尝试将以下内容放入实现类中:


friend std::shared_ptr<InterfaceImpl> std::make_shared<InterfaceImpl>();
Run Code Online (Sandbox Code Playgroud)

它仍然无法编译.那么我也将另一个放入IInterface类.仍然没有快乐.我在这做错了什么?

编辑:用于编译的完整源文件,与"朋友"...

#include <memory>

class IInterface
{    
public:    
    friend std::shared_ptr&lt;IInterface> Create();     
    virtual void Method() = 0;
};

class InterfaceImpl : public IInterface
{    
public:     
    virtual void Method() {}

protected:    
    friend std::shared_ptr&lt;IInterface> Create();     
    InterfaceImpl() {}    
};

std::shared_ptr<IInterface> Create()
{
    std::shared_ptr<IInterface> object = std::make_shared<InterfaceImpl>();    
    return object;
}

void main()
{
    std::shared_ptr<IInterface> i = Create();   
}
Run Code Online (Sandbox Code Playgroud)

Geo*_*che 4

使用 VC10,您链接到的解决方案不起作用 - 实例的构造InterfaceImpl不会发生在 中make_shared,而是发生在 中的内部类型中std::tr1::_Ref_count_obj<Ty>::_Ref_count_obj(void)

我只是在你的情况下使用Create()函数 a而不是使用friendmake_shared()

class InterfaceImpl : public IInterface {
// ...    
protected:
    friend std::shared_ptr<IInterface> Create();
    InterfaceImpl() {}
};

std::shared_ptr<IInterface> Create() {
    return std::shared_ptr<IInterface>(new InterfaceImpl());
}
Run Code Online (Sandbox Code Playgroud)

...或者使用make_shared()您实际上可以友好地使用的自定义实现,而无需依赖丑陋的实现细节。

另一种方法是使用类似pass-key-idiom 的东西:

class InterfaceImpl : public IInterface {
public:
    class Key {
        friend std::shared_ptr<IInterface> Create();
        Key() {}
    };
    InterfaceImpl(const Key&) {}
};

std::shared_ptr<IInterface> Create() {
    std::shared_ptr<IInterface> object = 
        std::make_shared<InterfaceImpl>(InterfaceImpl::Key());
    return object;
}
Run Code Online (Sandbox Code Playgroud)