std:: enable_shared_from_this;公共vs私人



我使用shared_ptr's和enable_shared_from_this玩了一会儿,而我遇到了一些我不太理解的东西。

在我的第一次尝试中,我构造了这样的东西:

class shared_test : std::enable_shared_from_this<shared_test> {
public:
    void print(bool recursive) {
        if (recursive) {
            shared_from_this()->print(false);
        }
        std::cout << "printing" << std::endl;
    }
};

请注意这个类私下扩展了std::enable_shared_from_this。这显然会产生很大的不同,因为执行这样的命令:

int main() {
    auto t(std::make_shared<shared_test>());
    t->print(true);
    return 0;
}

抛出一个bad_weak_ptr异常。如果我将类定义从std::enable_shared_from_this更改为固有的,则只运行find.

为什么,我在这里错过了什么?是不是有一种方法可以使它为私有继承工作,因为shared_test类的"外部世界"不需要知道它是启用共享从这个…(至少,如果你问我,或者我又错过了什么?)

为什么,我在这里错过了什么?

要使shared_from_this起作用,enable_shared_from_this必须知道持有类的shared_ptr。在STL实现中,它是weak_ptr,通过其他实现也是可能的。当您私有继承时,就不可能从类的外部访问基类的属性。实际上,你甚至不可能理解你从。因此,make_shared生成通常的shared_ptr初始化,而不需要在enable_shared_from_this中设置适当的字段。

异常不是从make_shared抛出,而是从shared_from_this抛出,因为enable_shared_from_this没有正确初始化。

是不是有一种方法可以让它为私有继承工作,因为shared_test类的"外部世界"不需要知道它是启用共享的…

。外部世界必须知道对象与shared_ptr有特殊关系才能正常工作

是否有办法使它为私有继承工作,因为shared_test类的"外部世界"不需要知道它从这个

启用了共享

shared_ptr本身是'外部世界'的一部分;为了初始化enable_shared_from_this实现的私有weak_ptr成员,shared_ptr构造函数需要能够访问它所指向的shared_test对象的enable_shared_from_this基类子对象。

我从STL代码中分析这个问题:

汽车t (std:: make_shared ());

代码行构造一个shared_ptr;首先我们深入研究make_shared函数

 // FUNCTION TEMPLATE make_shared
   template<class _Ty,
   class... _Types>
   NODISCARD inline shared_ptr<_Ty> make_shared(_Types&&... _Args)
   {    // make a shared_ptr
     const auto _Rx = new _Ref_count_obj<_Ty>(_STD forward<_Types>(_Args)...);
     shared_ptr<_Ty> _Ret;
    _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Getptr(), _Rx);
     return (_Ret);
   }

注意:我们深入研究函数_Ret.Set_ptr_rep_and_enable_shared。我们可以看到如下内容:

template<class _Ux>
   void _Set_ptr_rep_and_enable_shared(_Ux * _Px, _Ref_count_base * _Rx)
   {    // take ownership of _Px
        this->_Set_ptr_rep(_Px, _Rx);
        _Enable_shared_from_this(*this, _Px);
   }

我们找到function _Enable_shared_from_this,继续:

 template<class _Other,
    class _Yty>
    void _Enable_shared_from_this(const shared_ptr<_Other>& _This, _Yty * _Ptr)
    {   // possibly enable shared_from_this
    _Enable_shared_from_this1(_This, _Ptr, _Conjunction_t<
        negation<is_array<_Other>>,
        negation<is_volatile<_Yty>>,
        _Can_enable_shared<_Yty>>{});
   }

我们发现了一个关键点:_Can_enable_shared<_Yty>

template<class _Yty,
    class = void>
    struct _Can_enable_shared
        : false_type
    {   // detect unambiguous and accessible inheritance from enable_shared_from_this
    };
template<class _Yty>
    struct _Can_enable_shared<_Yty, void_t<typename _Yty::_Esft_type>>
        : is_convertible<remove_cv_t<_Yty> *, typename _Yty::_Esft_type *>::type
    {   // is_convertible is necessary to verify unambiguous inheritance
    };

我们发现只有_Yty有_Esft_type, _Yty可以转换为_Esft_type, _Yty可以被enable_shared(如果你想知道更多,那就看_Yty中的set weak_ptr,或者当你使用shared_from_this时,你可能会得到bad_weak_ptr错误)。那么_Esft_type是什么呢?

 template<class _Ty>
    class enable_shared_from_this
    {   // provide member functions that create shared_ptr to this
public:
    using _Esft_type = enable_shared_from_this;
     ...
   }

所以_Esft_type只是意味着enable_shared_from_this<_Ty>,所以如果你使用私有继承,外部不仅看不到_Esft_type而且_Yt也不能转换为_Esft_type。所以weak_ptr不能设置,所以可以调用bad_weak_ptr。

所以外部需要知道_Esft_type的存在,所以在构造shared_ptr时,也可以设置shared_test的weak_ptr。

根据文档,为了"shared_from_this"成员函数的可访问性,必须公开继承。

"公开继承std::enable_shared_from_this为类型T提供了一个成员函数shared_from_this" -来自CPP引用http://en.cppreference.com/w/cpp/memory/enable_shared_from_this

shared_from_this:

返回一个共享*this的所有权的shared_ptr(public member function)

相关内容

  • 没有找到相关文章

最新更新