可以在没有继承的情况下使用enable_shared_from_this吗?

时间:2015-12-02 12:18:37

标签: c++ inheritance destructor shared-ptr member

我发现的enable_shared_from_this示例显示它是通过继承使用的。例如:

struct Good : enable_shared_from_this<Good> {
    shared_ptr<Good> getptr() {
        return shared_from_this();
    }
};

int main() {
    // Good: the two shared_ptr's share the same object
    shared_ptr<Good> gp1(new Good);
    shared_ptr<Good> gp2 = gp1->getptr();
    cout << "gp2.use_count() = " << gp2.use_count() << endl;
}

我一天被警告过很多关于继承标准库的危险。这段代码当然似乎分享了这些危险,例如:

struct A : enable_shared_from_this<A> {};
struct B : enable_shared_from_this<B> {};

如果我想创建struct C : A, B {};,那么粘着点显然是C::shared_from_this()。显然我们可以解决这个问题,但有一些固有的复杂性。

所以我的问题是,有没有办法将enable_shard_from_this用作has-a关系而不是is-a关系?

1 个答案:

答案 0 :(得分:3)

  

有没有办法将enable_shard_from_this用作has-a关系而不是is-a关系?

没有

enable_shared_from_this 假设被用作基类,所以盲目地应用针对其他情况的指南在这种情况下不起作用。

即使有充分的理由想要这样做(并且没有)它也不会起作用。导致enable_shared_from_this基础与拥有派生对象的shared_ptr共享所有权的魔力通过检查继承而起作用。

enable_shared_from_this无论如何都不建模IS-A关系,因为它没有根据虚函数定义的接口。 IS-A表示扩展基本接口的派生类型,但这不是这种情况。 Good IS-NOT-A enable_shared_from_this<Good>

即。使用继承并不总是意味着IS-A关系。

  
      
  1. enable_shared_from_this没有虚拟析构函数
  2.   

虚拟析构函数是无关紧要的,除非您计划通过指向enable_shared_from_this基类的指针删除该对象,这将是疯狂的。没有理由传递Good作为指向enable_shared_from_this<Good>基类的指针,更不用说在该基指针上使用delete(通常会存储类型)在shared_ptr<Good>创建后,您就永远不会使用delete

enable_shared_from_this是一个mixin类型,而不是一个抽象基础。它提供了shared_from_this(以及很快weak_from_this)成员,这就是全部。您不应将其用作抽象基类或接口类型,也不应使用基类型来访问派生类型的多态行为。它根本没有虚函数,而不仅仅是没有虚析构函数,应该告诉你。

此外,正如上午如上所述,析构函数受到保护,因此即使您尝试过,也无法通过基类删除它(受保护的析构函数是防止滥用mixin类的惯用方法是非多态的基类)。

  
      
  1. enable_shared_from_this析构函数会破坏*this,这意味着它必须始终是最后一个名为
  2. 的析构函数   

咦?不确定你的意思,但除了自己和自己的数据成员之外,它不负责销毁任何东西。

  
      
  1. 继承自enable_shared_from_this的两个类的继承可能会成为一个棘手的问题
  2.   

它应该工作正常(尽管如果没有一个明确的基类是enable_shared_from_this的特化,你可能无法获得神奇的所有权共享)。 GCC标准库有一个错误(现已修复)无法编译,而不是仅仅无法共享所有权,但enable_shared_from_this没有问题。