代码之家  ›  专栏  ›  技术社区  ›  Robinson

使用make\u与受保护的构造函数+抽象接口共享

  •  5
  • Robinson  · 技术社区  · 14 年前

    例如:

    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;
    }
    

    make\u shared显然无法访问InterfaceImpl或IInterface中受保护的构造函数,从而导致以下错误

    
    error C2248: 'InterfaceImpl::InterfaceImpl' : cannot access protected member declared in class 'InterfaceImpl'
    

    在这里阅读(问题: How to make boost::make_shared a friend of my class ),我尝试将以下内容放入实现类中:

    
    friend std::shared_ptr<InterfaceImpl> std::make_shared<InterfaceImpl>();
    

    它仍然无法编译。所以我把另一个也放到了界面课上。还是没有快乐。我做错什么了?

    编辑:完整的源文件用来编译,与“朋友”。。。

    #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();   
    }
    
    2 回复  |  直到 7 年前
        1
  •  4
  •   Community Mr_and_Mrs_D    7 年前

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

    我只想做一个 Create() 函数a friend 在你的情况下 不使用 make_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());
    }
    

    ... 或者使用自定义 实际上,您可以在不依赖难看的实现细节的情况下与之成为朋友的实现。

    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;
    }
    
        2
  •  4
  •   Tom    12 年前

    对于最初的问题,std::make_shared<…>()没有直接实例化类,因此提供对它的友元访问不会产生任何好处,正如您所发现的那样。您只需提供对直接使用受保护构造函数的代码的友好访问,如下所示:

    friend class std::tr1::_Ref_count_obj<TheClassManagedByTheShared_Ptr>;
    

    friend class std::tr1::_Ref_count_obj<InterfaceImpl>;
    

    这适用于VS2010中的Microsoft编译器,但看起来它可能是特定于环境的,因为它不适用于Linux上的gcc。对于gcc,std::tr1命名空间不存在,因此它必须特定于std库的Microsoft实现。

    我的正常工作环境是英特尔12.1编译器,它似乎有一个根本不检查访问权限的bug,并且很高兴在没有任何友元声明的情况下构建代码。