std::enable_shared_from_this; public 与私人
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;
}
};
请注意,此 class 正在私下扩展 std::enable_shared_from_this。这显然有很大的不同,因为执行这样的事情:
int main() {
auto t(std::make_shared<shared_test>());
t->print(true);
return 0;
}
引发 bad_weak_ptr 异常。就好像我将 class 定义从 std::enable_shared_from_this 公开更改为固有的 运行 只是找到。
为什么会这样,我在这里想念什么?并且没有办法让它适用于私有继承,因为 shared_test class 的 'outside world' 不需要知道它正在启用共享...(至少,如果你问我,我不会再错过什么了吗?)
Why is that, what do I miss here?
要使 shared_from_this
工作,enable_shared_from_this
必须知道 shared_ptr
持有 class。在您的 STL 实现中它是 weak_ptr
,通过其他实现也是可能的。当您私有继承时,就不可能从您的 class 外部访问基 class 的属性。实际上甚至不可能理解你继承自。因此 make_shared
生成通常的 shared_ptr 初始化,而没有在 enable_shared_from_this
.
中设置适当的字段
异常不是从 make_shared
而是从 shared_from_this
抛出的,因为 enable_shared_from_this
没有正确初始化。
And isn't there a way to make it work for private inheritance, since the 'outside world' of the shared_test class does not need to know that it is enabling shared from this...
没有。外部世界必须知道该对象与 shared_ptr 有特殊关系才能正常使用它。
根据文档,为了 "shared_from_this" 成员函数的可访问性,必须继承 publicly。
"Publicly inheriting from std::enable_shared_from_this provides the type T with a member function shared_from_this" - 来自 CPP 参考
http://en.cppreference.com/w/cpp/memory/enable_shared_from_this
shared_from_this:
returns a shared_ptr 共享 *this 的所有权
(public成员函数)
isn't there a way to make it work for private inheritance, since the 'outside world' of the shared_test class does not need to know that it is enabling shared from this
shared_ptr
本身就是'outside world'的一部分; shared_ptr
构造函数需要能够访问它指向的 shared_test
对象的 enable_shared_from_this
基础 class 子对象,以便初始化私有 weak_ptr
成员enable_shared_from_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.And我们可以看到如下:
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吗(如果想了解更多,那就看set weak_ptr in _Yty,否则当你使用 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;
...
}
so _Esft_type只是表示enable_shared_from_this<_Ty>,所以如果使用private继承的话,outside不仅看不到_Esft_type而且_Yt也无法转换为_Esft_type。所以不能设置weak_ptr所以bad_weak_ptr可能会被调用
所以外部需要知道_Esft_type的存在,所以构造shared_ptr时,也可以设置shared_test的weak_ptr
我使用 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;
}
};
请注意,此 class 正在私下扩展 std::enable_shared_from_this。这显然有很大的不同,因为执行这样的事情:
int main() {
auto t(std::make_shared<shared_test>());
t->print(true);
return 0;
}
引发 bad_weak_ptr 异常。就好像我将 class 定义从 std::enable_shared_from_this 公开更改为固有的 运行 只是找到。
为什么会这样,我在这里想念什么?并且没有办法让它适用于私有继承,因为 shared_test class 的 'outside world' 不需要知道它正在启用共享...(至少,如果你问我,我不会再错过什么了吗?)
Why is that, what do I miss here?
要使 shared_from_this
工作,enable_shared_from_this
必须知道 shared_ptr
持有 class。在您的 STL 实现中它是 weak_ptr
,通过其他实现也是可能的。当您私有继承时,就不可能从您的 class 外部访问基 class 的属性。实际上甚至不可能理解你继承自。因此 make_shared
生成通常的 shared_ptr 初始化,而没有在 enable_shared_from_this
.
异常不是从 make_shared
而是从 shared_from_this
抛出的,因为 enable_shared_from_this
没有正确初始化。
And isn't there a way to make it work for private inheritance, since the 'outside world' of the shared_test class does not need to know that it is enabling shared from this...
没有。外部世界必须知道该对象与 shared_ptr 有特殊关系才能正常使用它。
根据文档,为了 "shared_from_this" 成员函数的可访问性,必须继承 publicly。
"Publicly inheriting from std::enable_shared_from_this provides the type T with a member function shared_from_this" - 来自 CPP 参考 http://en.cppreference.com/w/cpp/memory/enable_shared_from_this
shared_from_this:
returns a shared_ptr 共享 *this 的所有权 (public成员函数)
isn't there a way to make it work for private inheritance, since the 'outside world' of the shared_test class does not need to know that it is enabling shared from this
shared_ptr
本身就是'outside world'的一部分; shared_ptr
构造函数需要能够访问它指向的 shared_test
对象的 enable_shared_from_this
基础 class 子对象,以便初始化私有 weak_ptr
成员enable_shared_from_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.And我们可以看到如下:
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吗(如果想了解更多,那就看set weak_ptr in _Yty,否则当你使用 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;
...
}
so _Esft_type只是表示enable_shared_from_this<_Ty>,所以如果使用private继承的话,outside不仅看不到_Esft_type而且_Yt也无法转换为_Esft_type。所以不能设置weak_ptr所以bad_weak_ptr可能会被调用
所以外部需要知道_Esft_type的存在,所以构造shared_ptr时,也可以设置shared_test的weak_ptr