2016-10-08 193 views
9

我在使用shared_ptr和enable_shared_from_this時玩了一會兒,而遇到了一些我不太瞭解的東西。std :: enable_shared_from_this;公共vs私人

在我第一次嘗試我構建了這樣的事情:

class shared_test : std::enable_shared_from_this<shared_test> { 
public: 
    void print(bool recursive) { 
     if (recursive) { 
      shared_from_this()->print(false); 
     } 

     std::cout << "printing" << std::endl; 
    } 
}; 

請注意,這個類擴展的std :: enable_shared_from_this私人。這顯然造成了很大的不同,因爲執行這樣的事情:

int main() { 
    auto t(std::make_shared<shared_test>()); 
    t->print(true); 
    return 0; 
} 

拋出一個bad_weak_ptr異常。在這裏我好像將類定義更改爲std :: enable_shared_from_this公開的固有內容,這隻會發現。

這是爲什麼,我在這裏錯過了什麼?並且沒有辦法使它適用於私有繼承,因爲shared_test類的「外部世界」不需要知道它是從這個共享中啓用的......(至少,如果你問我,或者我再次錯過什麼?)

回答

6

爲什麼會這樣,我在這裏錯過了什麼?

爲了使shared_from_this工作enable_shared_from_this有了解shared_ptr持有的類。在你的STL實現中,它是weak_ptr,通過其他實現是可能的。當你私下繼承時,就不可能從你的類的外部訪問基類的屬性。事實上,你甚至不可能知道你已經繼承了。因此make_shared生成通常的shared_ptr初始化,但不在enable_shared_from_this中設置適當的字段。

異常不是從make_shared中拋出,而是從shared_from_this中拋出,因爲enable_shared_from_this未正確初始化。

而且是不是有辦法讓它爲私有繼承工作,因爲shared_test類中的「外面的世界」並不需要知道它是實現從這個共享...

不需要。外部世界必須知道該對象與shared_ptr有特殊關係才能正常使用它。

+0

有趣的是,錯誤是運行時錯誤,而不是私人訪問編譯錯誤。在我能想到的所有其他情況下,佈局,決心,......完全沒有區別。訪問控制是最後一次獨立完成的,其中#define private public給出相同的目標文件。 –

+0

@JohanLundberg對於「外部世界」,私有繼承與無繼承之間沒有(邏輯)區別。私有繼承意味着'is_base_of ,shared_test>'爲false,這是一個編譯時測試,它控制'shared_ptr'構造函數生成的代碼。 – Oktalist

+0

@Oktalist。謝謝 - 我遵循。我在評論中寫的很明顯並不適用於繼承。 –

0

根據文檔,必須公開繼承「shared_from_this」成員函數的可訪問性。

「從公開的std :: enable_shared_from_this繼承提供類型T與一個成員函數shared_from_this」 - 從CPP參考 http://en.cppreference.com/w/cpp/memory/enable_shared_from_this

shared_from_this:

返回這股的*所有權此 (公衆一個shared_ptr成員函數)

+0

您的回答實際上並沒有在問題中添加任何新內容:shared_from_this必須公開繼承。有趣的部分是爲什麼有這樣的限制。 –

+0

「enable_shared_from_this」應該被繼承.....而不是「shared_from_this」。而「shared_from_this」是返回「* this」指針的基類內部的一個函數。請注意,類名和它的函數名之間有一個額外的字「enable_」。 – Naidu

+0

而且你知道的是...... Base類的受保護和公共成員成爲Derived類的私有成員。因此,沒有其他類的成員可以通過派生類對象訪問,因爲它們在派生類中是私有的。 – Naidu

5

沒有辦法讓它適用於私有繼承,因爲shared_test類的'外部世界'不需要知道這個t它是從這個共享

shared_ptr本身是「外部世界」的一部分; shared_ptr構造函數需要能夠訪問它指向的shared_test對象的enable_shared_from_this基類子對象,以便初始化enable_shared_from_this實現的專用weak_ptr成員。