簡體   English   中英

的std :: enable_shared_from_this; 公共與私人

[英]std::enable_shared_from_this; public vs private

我正在玩一些使用shared_ptr和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公開更改為固有的,這只是查找。

為什么,我在這里想念什么? 並沒有辦法使它適用於私有繼承,因為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本身就是“外部世界”的一部分; shared_ptr構造函數需要能夠訪問它指向的shared_test對象的enable_shared_from_this基類子對象,以便初始化enable_shared_from_this實現的私有weak_ptr成員。

根據文檔,必須公開繼承“shared_from_this”成員函數的accessiblity。

“公開繼承自std :: enable_shared_from_this,為類型T提供成員函數shared_from_this” - 來自CPP參考http://en.cppreference.com/w/cpp/memory/enable_shared_from_this

shared_from_this:

返回一個shared_ptr,它共享* this(公共成員函數)的所有權

我從STL的代碼中分析了這個問題:

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

所以我們找到函數_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中看到設置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。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM