如何启用父级和派生级的_shared_from_this
我有简单的基类和派生类,我希望它们都具有 shared_from_this()
。
这个简单的解决方案:
class foo : public enable_shared_from_this<foo> {
void foo_do_it()
{
cout<<"foo::do_it\n";
}
public:
virtual function<void()> get_callback()
{
return boost::bind(&foo::foo_do_it,shared_from_this());
}
virtual ~foo() {};
};
class bar1 : public foo , public enable_shared_from_this<bar1> {
using enable_shared_from_this<bar1>::shared_from_this;
void bar1_do_it()
{
cout<<"foo::do_it\n";
}
public:
virtual function<void()> get_callback()
{
return boost::bind(&bar1::bar1_do_it,shared_from_this());
}
};
在以下代码中导致异常tr1::bad_weak_ptr
:
shared_ptr<foo> ptr(shared_ptr<foo>(new bar1));
function<void()> f=ptr->get_callback();
f();
所以在“谷歌搜索”之后我找到了以下解决方案:
class bar2 : public foo {
void bar2_do_it()
{
cout<<"foo::do_it\n";
}
shared_ptr<bar2> shared_from_this()
{
return boost::static_pointer_cast<bar2>(foo::shared_from_this());
}
public:
virtual function<void()> get_callback()
{
return boost::bind(&bar2::bar2_do_it,shared_from_this());
}
};
现在它可以工作了。
有没有更好、更方便、更正确的方法来为父子双方enable_shared_from_this
?
谢谢
I have simple base and derived class that I want both have shared_from_this()
.
This simple solution:
class foo : public enable_shared_from_this<foo> {
void foo_do_it()
{
cout<<"foo::do_it\n";
}
public:
virtual function<void()> get_callback()
{
return boost::bind(&foo::foo_do_it,shared_from_this());
}
virtual ~foo() {};
};
class bar1 : public foo , public enable_shared_from_this<bar1> {
using enable_shared_from_this<bar1>::shared_from_this;
void bar1_do_it()
{
cout<<"foo::do_it\n";
}
public:
virtual function<void()> get_callback()
{
return boost::bind(&bar1::bar1_do_it,shared_from_this());
}
};
Causes exception tr1::bad_weak_ptr
in following code:
shared_ptr<foo> ptr(shared_ptr<foo>(new bar1));
function<void()> f=ptr->get_callback();
f();
So after "googling" I have found following solution:
class bar2 : public foo {
void bar2_do_it()
{
cout<<"foo::do_it\n";
}
shared_ptr<bar2> shared_from_this()
{
return boost::static_pointer_cast<bar2>(foo::shared_from_this());
}
public:
virtual function<void()> get_callback()
{
return boost::bind(&bar2::bar2_do_it,shared_from_this());
}
};
And now it works.
Is there any better and more convinient and correct way to enable_shared_from_this
for both parent and child?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
通过在基类上定义以下内容可以使 OP 解决方案更加方便。
通过将其放置在基类中(以便重用)可以使这变得更加方便。
然后从中推导出如下。
The OP solution can be made more convenient by defining the following on the base class.
This can be made more convenient by placing it in a base class (for reuse).
and then deriving from it as follows.
抱歉,没有。
问题是
shared_ptr
和shared_ptr
是不同的类型。 我不明白幕后发生的一切,但我认为当构造函数返回并分配给shared_ptr
时,内部weak_ptr
发现没有任何东西指向它(因为只有shared_ptr
会增加计数器)并重置自身。 当您在get_callback
中调用bar1::shared_from_this
时,您会收到异常,因为内部weak_ptr
未指向任何内容。本质上,enable_shared_from_this 似乎只能从层次结构中的单个类透明地工作。 如果您尝试手动实现,问题应该变得明显。
Sorry, but there isn't.
The problem is that
shared_ptr<foo>
andshared_ptr<bar1>
are different types. I don't understand everything that's going on under the hood, but I think that when the constructor returns and is assigned to ashared_ptr<foo>
, the internalweak_ptr<bar1>
sees that nothing is pointing to it (because only ashared_ptr<bar1>
would increment the counter) and resets itself. When you callbar1::shared_from_this
inget_callback
, you get the exception because the internalweak_ptr
isn't pointing to anything.Essentially,
enable_shared_from_this
only seems to work transparently from a single class in a hierarchy. If you try implementing it manually, the problem should become obvious.如果您想要实现
shared_from_this()
函数,则与 @evoskuil 类似的解决方案可以减少派生类中的样板文件,从而在类中使用时生成以下代码:This using 'shim'functions课堂之外。 通过这种方式,它还为接口无法修改但派生自
enable_shared_from_this
的类提供了一种干净的方法 - 例如注意:使用
auto
进行返回这里的类型取决于编译器的年龄。可以放置在库头中的填充函数:
上面的代码依赖于这样一个事实:传递给
shared_from(...)
的类型继承自std::enable_shared_from_this 在其祖先的某个时刻。
调用
shared_from_base
将找出最终的类型。 由于我们知道That
继承自Base
,因此可以进行静态向下转型。可能存在一些病态的极端情况,其中的类具有类型转换运算符..但这不太可能发生在未设计来破坏此问题的代码中。
示例:
编译测试:
https://onlinegdb.com/SJWM5CYIG< /a>
先前的解决方案,我发布的,保留以使评论仍然有意义 - 这将函数放置在存在一些问题的基类中 - 特别是“正常”所需实现之间的不一致性类和模板类。
此外,对于新的类层次结构,需要重复基类中的实现,这并不是那么枯燥。
此外,基类函数可能会因从不同对象提供基类指针而遭受误用。 上面的新方案完全避免了这种情况,并且运行时断言(...)检查继续进行。
旧的实现:
A similar solution to @evoskuil that reduces boilerplate in derived classes should you want to implement a
shared_from_this()
function, resulting in the following code at the point of use in the class:This uses 'shim' functions outside of the class. By doing it that way it also provides a clean way to do this for classes who's interface can't be modified but derive from
enable_shared_from_this
- e.g.Note: Use of
auto
for return types here will depend upon the age of your compiler.Shim functions that could be placed in a library header:
The above code relies on the fact that the type passed to
shared_from(...)
inherits fromstd::enable_shared_from_this<Base>
at some point in its ancestry.Calling
shared_from_base
will figure out what type that ultimately was. Since we know thatThat
inherits fromBase
, a static downcast can be made.Probably there are some pathological corner cases with classes having type conversion operators.. but that's unlikely to occur in code not designed to break this.
Example:
Compilation test:
https://onlinegdb.com/SJWM5CYIG
Prior solution that I posted, kept to make the comments still make sense - this placed the functions in the base class which had some problems - particularly non-uniformity between the required implementation for 'normal' classes and template classes.
Additionally the implementation in the base class would need to be repeated for new class hierarchies which is not all that DRY.
Furthermore the base class function suffered from the possibility of misuse by supplying a base class pointer from a different object. The newer scheme above avoids this entirely and the runtime assert(...) check goes.
Old implementation:
很容易; 仅在您的基类中继承
public shared_from_this
。 在派生类中实现一个访问器,将其转换为适当的类型;Quite easy; inherit
public shared_from_this
only in your base class. Implement an accessor in your derived class that casts to the appropriate type;通过 c++23 推导这一点,事情变得容易多了。 https://godbolt.org/z/j499WK58Y
这是之前的答案:
嗯,我不知道不喜欢虚函数。 虚函数只是用于类型擦除,但我们并不总是需要类型擦除。 因此,提供一种类型擦除机制就足够了。 这是一个不使用虚函数的示例:
With c++23 deducing this, things become much easier. https://godbolt.org/z/j499WK58Y
This is the previous answer:
Well, I don't like virtual function. Virtual function is just for type erasing, but we don't need type erasing all the time. So, provide a mechanism for type erasing is enough. Here is an example that don't use virtual function: