接口方法并返回指向this (enable_shared_from_this)的智能指针

Interface methods and returning smart pointer to this (enable_shared_from_this)

本文关键字:this shared from 指针 智能 方法 返回 接口 enable      更新时间:2023-10-16

我有一个实现接口(LinkList)的类(Geometry)。在我的例子底部的代码显然是错误的,所以我正在考虑实现std::enable_shared_from_thisGeometry可以安全地从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使它们无用。

:

您可以使Geometryenable_shared_from_this<Geometry>派生(而不是从enable_shared_from_this<LinkList>派生,也不是从每个接口派生),并定义:

shared_ptr<LinkList> Geometry::getLinkList()
{
  return shared_from_this();
}

shared_from_this()返回的对象将隐式转换为shared_ptr<LinkList>。首先,您仍然需要thisshared_ptr拥有。