std::enable_shared_from_this使用

  玩过C++shared_ptr类型的智能指针的同学,是否有接触过std::enable_shared_from_this,它的出现为我们提供哪些编程方面的便利呢?下面就介绍它。

一、std::enable_shared_from_this的作用

  按照enable_shared_from_this - C++ Reference (cplusplus.com)文档介绍:继承std::enable_shared_from_this的子类,可以使用shared_from_this成员函数获取自身的shared_ptr指针;该类提供了允许继承类的对象创建指向自身实例的shared_ptr,并且与存在shared_ptr对象共享所有权。什么意思呢?我们接下来通过代码进行介绍。

二、如何使用std::enable_shared_from_this

  上面已经介绍了,需要定义一个继承类继承这个类,代码如下:

 1 namespace test_enable_shared_from_this{
 2 
 3     class Derived : public std::enable_shared_from_this<Derived>
 4     {
 5     public:
 6         void SetValue(int a)
 7         {
 8             _a = a;
 9         }
10         int GetValue() const
11         {
12             return _a;
13         }
14     private:
15         int _a;
16     };
17 
18 }

  那怎么使用这个继承类呢?我们分别在栈,堆上创建对象,然后调用shared_from_this成员函数返回的对象是啥。

  在栈上使用对象:

1 int main()
2 {
3     using namespace test_enable_shared_from_this;
4     Derived d;
5     auto obj = d.shared_from_this();
6     
7      return 0;  
8 }

      

  在栈上创建的对象不能调用该函数,会导致异常抛出:bad_weak_ptr。其实我们可以通过shared_from_this成员函数返回的是shared_ptr就知道不行,那么对象只能在堆上创建。能否裸指针呢?

1 int main()
2 {
3     using namespace test_enable_shared_from_this;
4     auto d = new Derived;
5     auto obj = d->shared_from_this();
6     
7     return 0;
8 }

       

  直接在堆上创建对象也不行。我们只能使用智能指针std::shared_ptr和unique_ptr,其实大家应该早就知道是哪个了,这里做详细说明是为了对问题的各种情况都进行验证加深对其使用。接下来我们使用

std::shared_ptr。

1 int main()
2 {
3     using namespace test_enable_shared_from_this;
4     auto d = std::shared_ptr<Derived>();
5     auto obj = d->shared_from_this();
6    
7     return 0;
8 }

       

  

  观察两个对象,完全一模一样。这就是文档上介绍std::enable_shared_from_this提供的一种机制。那我们试试std::unique_ptr:

int main()
{
    using namespace test_enable_shared_from_this;
    auto d = std::make_unique<Derived>();
    auto obj = d->shared_from_this();

    return 0;
}

       

   也不行。其实上面三种行不通的方式返回的指针都是空的。如下:

       

  所以使用shared_from_this的继承类对象只能是std::shared_ptr,其他方式都不行,如果误用的话,会导致返回的对象为空而出现其他问题。

三、std::enable_shared_from_this的继承问题

  我们上面只是继承一层,如果另外一个类继承上面的类,那能够正常使用shared_from_this函数吗?获取的对象是最后继承的吗?

  如下代码验证:

 1 namespace test_enable_shared_from_this{
 2 
 3     class Derived : public std::enable_shared_from_this<Derived>
 4     {
 5     public:
 6         void SetValue(int a)
 7         {
 8             _a = a;
 9         }
10         int GetValue() const
11         {
12             return _a;
13         }
14     private:
15         int _a;
16     };
17 
18     class Derived1 : public Derived
19     {
20     private:
21         int _b;
22     };
23 
24 }

   调用代码如下:

1 int main()
2 {
3     using namespace test_enable_shared_from_this;
4     auto d1 = std::make_shared<Derived1>();
5     auto obj = d1->shared_from_this();
6    
7     return 0;
8 }

  

   发现问题没有?虽然d1和obj对象地址一样,但是对象内存包含的成员属性不同。d1有自身的属性成员变量,但是obj没有,只含有基类的属性成员变量。是不是shared_from_this返回的对象中只包含那些直接继承

std::enable_shared_from_this呢?我们用多继承验证下:

 1 namespace test_enable_shared_from_this{
 2 
 3     class Derived : public std::enable_shared_from_this<Derived>
 4     {
 5     public:
 6         void SetValue(int a)
 7         {
 8             _a = a;
 9         }
10         int GetValue() const
11         {
12             return _a;
13         }
14     private:
15         int _a;
16     };
17 
18     class Derived1 : public std::enable_shared_from_this<Derived1>
19     {
20     private:
21         int _b;
22     };
23 
24     class Derived2 : public Derived, public Derived1
25     {
26     private:
27         int _c;
28     };
29 
30 }
1 int main()
2 {
3     using namespace test_enable_shared_from_this;
4     auto d2 = std::make_shared<Derived2>();
5     auto obj = d2->shared_from_this();
6  
7     return 0;
8 }

       

   直接提示执行不明确,这个很好理解,它不知道你究竟返回哪个子类std::shared_ptr。所以,继承类中不能存在多次继承std::enable_shared_from_this。哪个类继承的这个类,就返回这个类实例化的对象。我一般在其他类对象需要共享该类对象的情况下使用,这样该类就直接通过shared_ptr共享自身对象,如果其他类是通过引用或裸指针的方式共享该类,就不会继承这个类。

posted @ 2021-05-13 23:22  blackstar666  阅读(2561)  评论(0编辑  收藏  举报