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共享自身對象,如果其他類是通過引用或裸指針的方式共享該類,就不會繼承這個類。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM