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

时间:2014-08-01 18:19:23

标签: c++ interface shared-ptr smart-pointers

我有一个实现接口(Geometry)的类(LinkList)。我的示例底部的代码显然是错误的,所以我正在考虑实现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
}

1 个答案:

答案 0 :(得分:3)

  

我示例底部的代码显然是错误的

代码没有明显错误,该错误位于getLinkedList,它将this的所有权授予shared_ptr,导致printList返回时删除Geometry最后一个shared_ptr对象超出范围。因此,该示例的最后一行显然是非常错误的,因为前一行巧妙地删除了该对象。

  

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()

(当然使用printList(geom)在那里毫无意义,因为你已经拥有了sahred_ptr并且只能Geometry}。

  

如果我的enable_shared_from_this类有多个继承的接口会发生什么,我可以为所有接口执行此操作吗?

不,如果该类有多个shared_ptr基类,则enable_shared_from_this构造函数不知道要初始化哪一个。我认为你会因为含糊不清而收到错误,或者如果不是weak_ptr基类都会导致空Geometry使它们变得无用。

<强>更新

您可以enable_shared_from_this<Geometry>从[{1}}(不是来自enable_shared_from_this<LinkList>而不是来自每个界面)派生shared_ptr<LinkList> Geometry::getLinkList() { return shared_from_this(); } ,并定义:

shared_from_this()

shared_ptr<LinkList>返回的对象将隐式转换为this。首先,您仍然需要shared_ptr拥有{{1}}。