我有一个实现接口(LinkList
)的类(Geometry
)。在我的例子底部的代码显然是错误的,所以我正在考虑实现std::enable_shared_from_this
。Geometry
可以安全地从std::enable_shared_from_this<LinkList>
继承,我可以安全地改变getLinkList()
方法到shared_from_this()
吗?如果我的Geometry
类有它继承的多个接口会发生什么,我可以为所有的接口这样做吗?
class Link
{
public:
std::string getName() { return "the name"; }
};
class LinkList
{
public:
virtual Link* getLink(int id) = 0;
virtual int size() = 0;
};
class Geometry : LinkList
{
private:
int state;
public:
void doSomething() { state = 1; }
virtual Link* getLink(int id) { return new Link(); }
virtual int size() { return 1; }
std::shared_ptr<LinkList> getLinkList() { return std::shared_ptr<LinkList>(this); }
};
void printList(std::shared_ptr<LinkList> linkList)
{
for (int i = 0; i < linkList->size(); i++)
{
std::cout << linkList->getLink(i)->getName() << std::endl;
}
}
void main()
{
Geometry* geom = new Geometry();
printList(geom->getLinkList());
geom->doSomething(); // Error here
}
我的例子底部的代码显然是错误的
代码没有明显的错误,错误是在getLinkedList
中,它将this
的所有权赋予shared_ptr
,导致当printList
返回并且最后一个shared_ptr对象超出范围时将其删除。因此,示例的最后一行相当不明显地错误,因为前一行巧妙地删除了对象。
Geometry
可以安全地继承std::enable_shared_from_this<LinkList>
是的,它只是一个基类。从它继承它几乎总是安全的(但这并不意味着你可以安全地使用它!)
,我可以安全地将
getLinkList()
方法更改为shared_from_this()
吗?
仅当Geometry
对象为shared_ptr
所拥有,而在您的代码中它不是:
Geometry* geom = new Geometry();
您需要将指针存储在shared_ptr
中(最好在创建它时立即),以便enable_shared_from_this
基类可用,因此这应该是可以的:
auto geom = std::make_shared<Geometry>();
printList(geom->shared_from_this());
geom->doSomething();
(当然,在这里使用shared_from_this()
是毫无意义的,因为你已经有了sahred_ptr,可以只使用printList(geom)
)。
如果我的
Geometry
类有它继承的多个接口会发生什么,我可以为所有的接口这样做吗?
不,如果类有多个enable_shared_from_this
基类,那么shared_ptr
构造函数将不知道初始化哪个。我认为你会得到一个错误,由于歧义,或者如果没有enable_shared_from_this
基类都将持有一个空的weak_ptr
使它们无用。
:
您可以使Geometry
从enable_shared_from_this<Geometry>
派生(而不是从enable_shared_from_this<LinkList>
派生,也不是从每个接口派生),并定义:
shared_ptr<LinkList> Geometry::getLinkList()
{
return shared_from_this();
}
由shared_from_this()
返回的对象将隐式转换为shared_ptr<LinkList>
。首先,您仍然需要this
由shared_ptr
拥有。